Skip to content

[BUG] Function overloading with an @enum type produces unexpected results #687

Closed

Description

@guybrush77

Describe the bug

Function overloading with an @enum type produces unexpected results.

To Reproduce

Try the following code:

Color: @enum type = {
    RED;
    GREEN;
    BLUE;
}

foo: (color: Color) = {
    std::cout << "Invoked foo: (color: Color)\n";
}

foo: (color: _) = {
    std::cout << "Invoked foo: (color: _)\n";
}

main: () = {
    foo(Color::RED);
}

After running this program, I'd expect to see the following on stdout:

Invoked foo: (color: Color)

Instead, the generic function is called:

Invoked foo: (color: _)

Activity

  1. JohelEGP commented on Sep 17, 2023

    @JohelEGP
    Contributor

    This was hinted at #131 (comment).

  2. JohelEGP commented on Sep 17, 2023

    @JohelEGP
    Contributor

    This formulation seems to permit having seemingly static constexpr data members of the type being defined (https://compiler-explorer.com/z/7nY47a7YG):

    struct perms {
      unsigned underlying;
    
      static const perms read;
    };
    
    constexpr perms perms::read = {1};
    
    static_assert(perms::read.underlying == 1);
    
    #include <type_traits>
    
    static_assert(std::integral_constant<perms, perms::read>{}.value.underlying == 1);
  3. guybrush77 commented on Sep 17, 2023

    @guybrush77
    Author

    Thanks, I understand the underlying issue now.

    Still, I hope that the ergonomics can be improved. I think the new @enum fails to adhere to the principle of least astonishment.

  4. JohelEGP commented on Sep 19, 2023

    @JohelEGP
    Contributor

    Emitting object aliases at type-scope like above at #687 (comment)
    makes it possible for @enum and @flag_enum to have enumerators of the type of the enumeration.

    But it would also makes all other uses of them in the signatures of members impossible.
    Which I think is a much more common use case than having static data members of equal type.
    For example, see ref-is-glvalue at https://eel.is/c++draft/range.join.iterator.

  5. guybrush77 commented on Sep 19, 2023

    @guybrush77
    Author

    Right. I agree that using enums in signatures is a desirable feature.

    Anyway, I will close this bug since it is not really a bug, but more like a design tradeoff.

  6. JohelEGP commented on Sep 19, 2023

    @JohelEGP
    Contributor

    I view it as a bug that the enumerator doesn't have the type of the enumeration.
    I think using functions to return the enumerator values would be better.
    A Cpp1 enumerator is a platonic value.
    A Cpp2 enumerator is an object alias.
    But if Cpp2 enumerators were returned by a function,
    they'd once again become platonic values.

  7. JohelEGP commented on Sep 19, 2023

    @JohelEGP
    Contributor

    Although there'd be more resistance to migrating to Cpp2's @enum from Cpp1's enum if you had to call enumerators to get the value.
    And there's the chance of using the function pointer accidentally
    (and ah, we'd have function(s) (pointers) in addition to the platonic values).
    Perhaps it'd be better if Cpp2 simply treated type-scope object aliases with type equal to the type being defined specially
    and they were lowered like #687 (comment).
    Then we can all live happily.

  8. hsutter commented on Sep 19, 2023

    @hsutter
    Owner

    Ack: Yes, I'm looking at this now. I always intended for enumerators to have the type of the enumeration, but Cpp1 doesn't allow that, so the initial implementation worked around it.

    The solution I'm currently pursuing is to lower all type-scope object aliases as you suggest (see also https://stackoverflow.com/questions/11928089/), and then enumerators would Just Work too. That way I don't need to make enumerations a special case.

  9. hsutter commented on Sep 22, 2023

    @hsutter
    Owner

    I've now improved this in b589f5d

    Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions