Replace checks on enum declaration with subtype checks
Summary:
The type checking of `enum E : t` and `class E : Enum<t>` declarations is currently quite complex, needlessly so. In this diff we simply use subtyping to check the following
1. The enum constraint (after the `as`) is a subtype of `arraykey`. If no constraint is specified, it is assumed to *be* `arraykey`.
2. The underlying type (after the `:`) is a subtype of the constraint.
3. The enum values have types that are subtypes of the underlying type.
This is both more and less restrictive than the current implementation.
* It is less restrictive because the underlying type is permitted to be `arraykey`, so values can be a mixture of both ints and strings. This was already the case for the legacy form (`class E : Enum<t>`) but not for the enum declaration form.
* It is more restrictive because you can no longer break `newtype` abstraction: the underlying type or constraint on an enum cannot be an opaque `newtype`.
Reviewed By: dlreeves
Differential Revision:
D16419034
fbshipit-source-id:
c9a335d4d975b90362f5ec031ef2c9a2ac5d7496