Skip to content

How does one refine a mixed value to a HH\MemberOf<EnumClass, T> #1057

Open
@lexidor

Description

@lexidor

Where is the problem?

Missing section, as and is refinement.

What is the problem?

Enum classes don't have assert and coerce methods. It does have nameOf and valueOf, but the purpose of those isn't made clear. Interactions with as and is happen at the class level, not the member level. One can not do an as or is check with HH\MemberOf.

This is all probably intentionally not supported.


Please don't change anything below this point.


  • Build ID: HHVM=HHVM-4.117.0:HSL=v4.108.1:2021-07-07T22:16:22+0000:1fa47f258c6b68f8ec01899aa82fd6ffa0957109
  • Page requested: /hack/built-in-types/enum-class
  • Page requested at: Fri, 16 Jul 2021 11:13:26 +0000
  • Controller: GuidePageController

Activity

vsiles

vsiles commented on Nov 30, 2021

@vsiles
Contributor

@lexidor nameOf and valueOf will only be usable with enum class label (soon :p), they are not useful for MemberOf. I'm reluctant to add a coerce/assert method to enum class as it is not meant to be that way. If you get a mixed value, it is probably not from an enum class (otherwise you would have a memberof) so I don't want to coerce like enums allow (nasty design if you ask me).

Feel free to explain your use case in more detail and we can have a look together

lexidor

lexidor commented on Dec 1, 2021

@lexidor
ContributorAuthor

@lexidor nameOf and valueOf will only be usable with enum class label (soon :p), they are not useful for MemberOf. I'm reluctant to add a coerce/assert method to enum class as it is not meant to be that way. If you get a mixed value, it is probably not from an enum class (otherwise you would have a memberof) so I don't want to coerce like enums allow (nasty design if you ask me).

Feel free to explain your use case in more detail and we can have a look together

Plain enums can be used at API boundaries. These apis take a text request and turn this text into an untyped Hack value. You then need to assert that this value matches the expected type. There is currently no way to put enum classes at API boundaries, since you can't assert that the input matches the expected type. In fewer words, in a fully type sound world all values of type HH\MemberOf must originate from a "hard-coded" expression. This effectively means that any API that erases the type, but preserves the exact value, can not be used.

The work around would be codegenning an if else clain comparing supplied value using === to all members. If they compare equal, return the member. This would erase the value type to the backing type of the enum. So when passing an int to this function, your return would be a HH\MemberOf<ClassEnumBackedByMixed, mixed>. This is unsatisfactory, because the typechecker forgot that we already knew the value to be an int.

The boilerplate could be eliminated with a builtin. Code within hhvm does not have to satisfy the typechecker, so an implementation like the following can only work when it is part of the runtime.

final public static function assert<T, Tret as T&TBackingType>(T $v)[correct context]: HH\MemberOf<this, Tret> {
  foreach (self::enumerateAllMembers() as $m) if ($v === $m) return $v;
  throw ...;
}

This code can't be written in userland today, because the enumerateAllMembers method does not exist and the typechecker does not understand that the identity comparison between $v and $m constrains $v to be a subtype of TBackingType.

lexidor

lexidor commented on Dec 1, 2021

@lexidor
ContributorAuthor

I don't want to coerce like enums allow (nasty design if you ask me).

I dislike coercion more than most. Having is and as be unsound on plain enums is something I despise. Same goes for assert on plain enums returning ints when given an intish string and vice versa.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @AndrewDiMola@vsiles@lexidor

        Issue actions

          How does one refine a mixed value to a HH\MemberOf<EnumClass, T> · Issue #1057 · hhvm/user-documentation