Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix enum value's __int__ returning non-int when underlying type is bool or of char type #1334

Merged
merged 8 commits into from
Aug 26, 2021
Merged

Conversation

Vigilans
Copy link
Contributor

@Vigilans Vigilans commented Mar 23, 2018

Introduction

This PR solves the problem of enum value's __int__ returning a non-int value when its underlying type is bool or of char type.

Detail

This PR extends the enum_ class with following type alias:

  • Underlying type: the actual underlying type of enum (The original Scalar type);
  • Scalar type: the integer type with length and signedness equivalent to the underlying type.

The enum should always use Scalar as the inner integer type when dealing with python side.

So,

  • Scalar for underlying type of normal integer would stay the same;
  • Scalar for underlying type of bool or char type would use the int type of same length and signedness, specified through the equivalent_integer struct.

Applicable issues

Fix #1331
Fix #1820
Fix osmcode/pyosmium#114

Suggested changelog entry:

Bug fix: enum value's `__int__` returning non-int when underlying type is bool or of char type. Fixes #1331, #1820.

@jagerman
Copy link
Member

Is unsigned char (or, for that matter, signed char, which is also distinct from char and unsigned char) necessary here? That is_std_char_type template is there to capture the types that are used for strings, which is pretty much just char. It shouldn't be catching unsigned char and signed char in the first place--those should fall through to the arithmetic converter.

@Vigilans
Copy link
Contributor Author

Vigilans commented Mar 25, 2018

@jagerman

I see. It corresponds to the compile error which seems to tell me that unsigned char is used as an arithmetic type, instead of an element of string, which is listed inside the is_std_char_type.

@Vigilans
Copy link
Contributor Author

Vigilans commented Dec 3, 2019

Sorry for my foolishness of not getting your point and suspended this PR for one year long...

I've updated the PR to keep pace with the master, and fixed it with a more robust mechanism, along with more tests, to solve both issues of char and bool types.

My original post for context reference:

I followed the suggestion mentioned in the issue and now the bug is eliminated.

BTW, It should be noted that the definition of detailed::is_std_char_type does not check unsigned char:

template <typename CharT> using is_std_char_type = any_of<
    std::is_same<CharT, char>, /* std::string */
    std::is_same<CharT, char16_t>, /* std::u16string */
    std::is_same<CharT, char32_t>, /* std::u32string */
    std::is_same<CharT, wchar_t> /* std::wstring */
>;

And when I tried to add unsigned char to the type list, compile errors occurred. Therefore, I alternatively turn to add it to the definition of enum_<Type>::ScalarInt:

using ScalarInt = detail::conditional_t<
    detail::is_std_char_type<Scalar>::value || std::is_same<Scalar, unsigned char>::value,
    detail::conditional_t<std::is_signed<Scalar>::value, int, unsigned>,
    Scalar>;

@Vigilans Vigilans changed the title Fix __int__ and __hash__'s TypeError when enum's underlying type is of char type Fix enum value's __int__ returning non-int when underlying type is bool or of char type Dec 3, 2019
@Vigilans Vigilans closed this Dec 12, 2019
@Vigilans Vigilans reopened this Dec 12, 2019
@Vigilans Vigilans closed this Dec 12, 2019
@Vigilans Vigilans reopened this Dec 12, 2019
@Vigilans
Copy link
Contributor Author

Vigilans commented Dec 12, 2019

Hi @wjakob @jagerman, now CI has been fixed, would you please take some time to review it?

@ax3l ax3l added the bug label Dec 18, 2020
@ax3l
Copy link
Collaborator

ax3l commented Dec 18, 2020

HI @Vigilans - looking through unfixed problems with propose solutions, do you think it would be possible to rebase this pull request for a new round of review? Sorry for the long delay on this!

std::is_same<py::enum_<ScopedChar32Enum>::Scalar, std::uint_least32_t>,
std::is_same<py::enum_<ScopedChar16Enum>::Scalar, std::uint_least16_t>
>::value, "char32_t, char16_t (and char8_t)'s size, signedness, and alignment is determined");
#if defined(PYBIND11_CPP20)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a nit: we should probably start testing the CPP20 soon.

Copy link
Contributor Author

@Vigilans Vigilans Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your rebase and review! And sorry for my long delay on last comment since I didn't check github's email frequently at that time...

What should I do to help the testing of CPP20 in this pull request? As shown in detail::is_std_char_type's implementation:

template <typename CharT> using is_std_char_type = any_of<
std::is_same<CharT, char>, /* std::string */
#if defined(PYBIND11_HAS_U8STRING)
std::is_same<CharT, char8_t>, /* std::u8string */
#endif
std::is_same<CharT, char16_t>, /* std::u16string */
std::is_same<CharT, char32_t>, /* std::u32string */
std::is_same<CharT, wchar_t> /* std::wstring */
>;

Should I replace the PYBIND11_CPP20 macro with PYBIND11_HAS_U8STRING in this test?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should I do to help the testing of CPP20 in this pull request?

The first step is on us (Aaron, Henry, me), we need to add a job to the CI.
Not sure if we should block this PR on that, or merge this PR first and then fix up as needed when establishing the CPP20 job. I'm fine either way.

tests/test_enum.py Outdated Show resolved Hide resolved
tests/test_enum.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks! Could you please leave a small comment "ready to merge!" when it is. (I see you made a series of small changes, therefore I'm not sure if you're still working on something.)

@Vigilans
Copy link
Contributor Author

Vigilans commented Aug 26, 2021

@rwgk Thanks for your patience! I'm working on satisfying the formatter and fixing test failure in some python 2.7 platforms (__getstate__() and __hash__() returns long type instead of int in these py2.7 platforms). When all the CI passed I'll leave a ready comment here.

@Vigilans
Copy link
Contributor Author

Vigilans commented Aug 26, 2021

@rwgk Seems some of the workflows need further approval. Personally I think it is ready to merge with:

  • PYBIND11_CPP20 macro changed to PYBIND11_HAS_U8STRING and tested on a char8_t available environment settings.
  • Python side tests modified to be supposed to pass in both python 3.x and python 2.x environments.

@rwgk
Copy link
Collaborator

rwgk commented Aug 26, 2021

CI all green! Thanks @Vigilans and all reviewers. Merging.

@rwgk rwgk merged commit cb60ed4 into pybind:master Aug 26, 2021
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Aug 26, 2021
rwgk pushed a commit that referenced this pull request Aug 31, 2021
…nt when underlying type is bool or of char type) (#3232)

* Minor tweaks.

* Restoring tests/pybind11_tests.h version from master, removing just the comment and empty line that was added in PR #3087; those were made obsolete by the pragma cleanup that concluded with PR #3186.

* More-to-the-point test for Python 3.
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
6 participants