Version 2.17.0-128.0.dev
Merge commit 'db30a5f6702c8bc8dfe3c63ac7c662939d3f2351' into 'dev'
diff --git a/tests/language/enum/enhanced_enums_basic_test.dart b/tests/language/enum/enhanced_enums_basic_test.dart
index 655a1f0..07f65d0 100644
--- a/tests/language/enum/enhanced_enums_basic_test.dart
+++ b/tests/language/enum/enhanced_enums_basic_test.dart
@@ -19,10 +19,10 @@
Expect.identical(EnumPlainTrailingComma.v2, EnumPlainTrailingComma.values[1]);
Expect.identical(EnumPlainTrailingComma.v3, EnumPlainTrailingComma.values[2]);
- Expect.equals(3, EnumPlainNoSemicolon.values.length);
- Expect.identical(EnumPlainNoSemicolon.v1, EnumPlainNoSemicolon.values[0]);
- Expect.identical(EnumPlainNoSemicolon.v2, EnumPlainNoSemicolon.values[1]);
- Expect.identical(EnumPlainNoSemicolon.v3, EnumPlainNoSemicolon.values[2]);
+ Expect.equals(3, EnumNoSemicolon.values.length);
+ Expect.identical(EnumNoSemicolon.v1, EnumNoSemicolon.values[0]);
+ Expect.identical(EnumNoSemicolon.v2, EnumNoSemicolon.values[1]);
+ Expect.identical(EnumNoSemicolon.v3, EnumNoSemicolon.values[2]);
Expect.type<EnumNoSemicolon<num>>(EnumNoSemicolon.v1);
Expect.equals(3, EnumPlainSemicolon.values.length);
@@ -69,13 +69,13 @@
Expect.identical(EnumAll.v1, EnumAll.sLateFinal);
Expect.throws(() => EnumAll.sLateFinal = EnumAll.v1);
- Expect.identical(EnumAll.v3, EnumAll.sFinalInit);
+ Expect.identical(EnumAll.v3, EnumAll.sFinal);
- Expect.throws(() => EnumAll.sLate);
- EnumAll.sLate = EnumAll.v1;
- Expect.identical(EnumAll.v1, EnumAll.sLate);
- EnumAll.sLate = EnumAll.v3;
- Expect.identical(EnumAll.v3, EnumAll.sLate);
+ Expect.throws(() => EnumAll.sLateVar);
+ EnumAll.sLateVar = EnumAll.v1;
+ Expect.identical(EnumAll.v1, EnumAll.sLateVar);
+ EnumAll.sLateVar = EnumAll.v3;
+ Expect.identical(EnumAll.v3, EnumAll.sLateVar);
Expect.identical(EnumAll.v3, EnumAll.sLateVarInit);
Expect.isNull(EnumAll.sVar);
Expect.identical(EnumAll.v3, EnumAll.sVarInit);
@@ -90,8 +90,8 @@
// Access static members through typedef.
Expect.identical(EnumAll.v3, TypeDefAll.sConst);
Expect.identical(EnumAll.v3, TypeDefAll.sFinal);
- Expect.identical(EnumAll.v1, TypedefAll.sLateFinal);
- Expect.identical(EnumAll.v3, TypedefAll.sFinalInit);
+ Expect.identical(EnumAll.v1, TypeDefAll.sLateFinal);
+ Expect.identical(EnumAll.v3, TypeDefAll.sLateFinalInit);
Expect.identical(EnumAll.v3, TypeDefAll.staticGetSet);
TypeDefAll.staticGetSet = EnumAll.v5;
@@ -129,24 +129,20 @@
// The `index` and `toString` implementations are inherited from
// the `Enum` implementing superclass.
- Expect.equals(3.5, StringIndexEnum.v1.index);
- Expect.equals(3.5, StringIndexEnum.v2.index);
- Expect.equals(0, StringIndexEnum.v1.realIndex);
- Expect.equals(1, StringIndexEnum.v2.realIndex);
+ Expect.equals(0, StringIndexEnum.v1.index);
+ Expect.equals(1, StringIndexEnum.v2.index);
+ Expect.equals(0, StringIndexEnum.v1.superIndex);
+ Expect.equals(1, StringIndexEnum.v2.superIndex);
Expect.equals("FakeString", StringIndexEnum.v1.toString());
Expect.equals("FakeString", StringIndexEnum.v2.toString());
Expect.equals("StringIndexEnum.v1", StringIndexEnum.v1.realToString());
Expect.equals("StringIndexEnum.v2", StringIndexEnum.v2.realToString());
// Enum elements are always distinct, even if their state doesn't differ.
- Expect.distinct(Canonical.v1, Canonical.v2, "Canonical - type only");
- Expect.distinct(Canonical.v2, Canonical.v3, "Canonical - no difference");
+ Expect.notIdentical(Canonical.v1, Canonical.v2, "Canonical - type only");
+ Expect.notIdentical(Canonical.v2, Canonical.v3, "Canonical - no difference");
- // A `values` static constant is added only if *not* causing a conflict.
- Expect.equals("StaticDeclaration", DeclaresValuesStatic.values);
- Expect.equals("Declaration", DeclaresValues.v1.values);
- Expect.equals("Mixin", InheritsValues.v1.values);
- Expect.equals("NSM", ImplementsValues.v1.values);
+ Expect.identical(SelfRefEnum.e1, SelfRefEnum.e2.previous, "SelfRef.prev");
}
// Original syntax still works, without semicolon after values.
@@ -251,16 +247,15 @@
return values[newIndex]; // Can refer to `values`.
}
- // Can have non-primitive equality and hashCode.
- int get hashCode => index;
- bool operator==(covariant EnumAll other) => index == other.index;
-
// Can access `this` and `super` in an instance method.
String thisAndSuper() => "${super.toString()}:${this.toString()}";
// Can be callable.
T call<T>(T value) => value;
+ // Can have an `index` setter.
+ set index(int value) {}
+
// Instance members shadow extensions.
String get notExtension => "not extension";
@@ -268,7 +263,10 @@
}
extension EnumAllExtension on EnumAll {
- String get notExtension => Expect.fail("Unreachable");
+ String get notExtension {
+ Expect.fail("Unreachable");
+ return "not";
+ }
String get extension => "extension";
}
@@ -280,7 +278,12 @@
v2.named(2);
final int x;
- EnumNoUnnamedConstructor.named(this.x);
+ const EnumNoUnnamedConstructor.named(this.x);
+}
+
+enum NewNamedConstructor {
+ v1;
+ const NewNamedConstructor.new();
}
// Can have an unnamed factory constructor.
@@ -290,7 +293,7 @@
final int x;
factory EnumFactoryUnnamedConstructor() => v1;
- EnumFactoryUnnamedConstructor.named(this.x);
+ const EnumFactoryUnnamedConstructor.named(this.x);
}
// Elements which do not differ in public state are still different.
@@ -300,35 +303,24 @@
v2<num>(1),
v3<num>(1);
final T value;
- Canonical(this.value);
+ const Canonical(this.value);
}
// Both `toString` and `index` are inherited from superclass.
enum StringIndexEnum {
v1, v2;
- num get index => 3.5;
- int get realIndex => super.index;
+ // Cannot override index
+ int get superIndex => super.index;
String toString() => "FakeString";
String realToString() => super.toString();
}
-enum DeclaresValuesStatic {
- v1;
- static String get values => "StaticDeclaration";
-}
-
-enum DeclaresValues {
- v1;
- String get values => "Declaration";
-}
-
-enum InheritsValues with ValuesMixin {
- v1;
-}
-
-enum ImplementsValues implements ValuesInterface {
- v1;
- dynamic noSuchMethod(i) => "NSM";
+// An enum value expression *can* reference another enum value.
+enum SelfRefEnum {
+ e1(null),
+ e2(e1);
+ final SelfRefEnum? previous;
+ const SelfRefEnum(this.previous);
}
// --------------------------------------------------------------------
@@ -360,11 +352,3 @@
// Implemented by mixins.
bool test(Object o);
}
-
-abstract class ValuesInterface {
- String get values;
-}
-
-mixin ValuesMixin {
- String get values => "Mixin";
-}
diff --git a/tests/language/enum/enhanced_enums_error_test.dart b/tests/language/enum/enhanced_enums_error_test.dart
new file mode 100644
index 0000000..169b538
--- /dev/null
+++ b/tests/language/enum/enhanced_enums_error_test.dart
@@ -0,0 +1,685 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=enhanced-enums
+
+// Test errors required by new enhanced enum syntax.
+
+// Enums must satisfy the same requirements as their induced class.
+// That means no name conflicts, no static/instance member conflicts,
+// and no type errors.
+// Enum classes must implement their interface.
+// They cannot override `Enum.index` or have any instance member named
+// `values` or declare any name which will conflicts with a static
+// constant getter named `values`.
+//
+// An enum declaration's generative constructors can never be referenced
+// other than implicitly in creating the values and as target of redirecting
+// generative constructors. All generative constructors must be const.
+//
+// An enum class cannot override `index` or implement anything named `values`.
+
+// Helper mixins and also used as interfaces.
+mixin GetFoo {
+ int get foo => 42;
+}
+
+mixin SetFoo {
+ void set foo(int _) {}
+}
+
+mixin MethodFoo {
+ int foo() => 42;
+}
+
+mixin ValuesGetter {
+ int get values => 42;
+}
+
+mixin IndexGetter {
+ int get index => 42;
+}
+
+mixin NeverIndexGetter {
+ Never get index => throw "Never!";
+}
+
+// "You cannot have two members with the same name in the same class---be
+// they declared or inherited"
+
+// Enums inherit members of `Object` and `index`.
+// Enums implicitly declare `values` and their enum values (as static const
+// getters.)
+
+enum ConflictInstanceMembers {
+ e1;
+ int get foo => 42;
+ int foo() => 37;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+ // [cfe] 'foo' is already declared in this scope.
+}
+
+// "It is an error if you have a static member named $m$ in your class
+// and an instance member of the same basename"
+enum ConflictStaticGetterInstanceMembers {
+ e1;
+ static int get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ int foo() => 37;
+ // ^
+ // [cfe] 'foo' is already declared in this scope.
+}
+
+enum ConflictStaticSetterInstanceMembers {
+ e1;
+ static void set foo(int _) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ // [cfe] This static member conflicts with an instance member.
+ int foo() => 37;
+ // ^^^
+ // [cfe] unspecified
+}
+
+enum ConflictStaticInstanceProperty2 {
+ e1;
+ int get foo => 42;
+ // ^^^
+ // [cfe] unspecified
+ static void set foo(int _) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ // [cfe] This static member conflicts with an instance member.
+}
+
+// "It is an error if you have a static getter $v$
+// and an instance setter \code{$v$=}"
+enum ConflictStaticInstanceProperty {
+ e1;
+ static int get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ // [cfe] This static member conflicts with an instance member.
+ void set foo(int _) {}
+ // ^^^
+ // [cfe] unspecified
+}
+
+
+enum ConflictStaticInheritedFoo with MethodFoo {
+ e1;
+ static int get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ConflictInheritedEnumValue with MethodFoo {
+ foo;
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+// [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ConflictStaticEnumValues {
+ e1,
+//^^
+// [cfe] unspecified
+ e1,
+//^^
+// [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+// [cfe] 'e1' is already declared in this scope.
+ ;
+}
+
+enum ConflictStaticEnumValuesLooksDifferent {
+ e1(),
+//^^
+// [cfe] unspecified
+ e1.value(42),
+//^^
+// [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+// [cfe] 'e1' is already declared in this scope.
+ ;
+ const ConflictStaticEnumValuesLooksDifferent();
+ const ConflictStaticEnumValuesLooksDifferent.value( dynamic_);
+}
+
+enum ConflictInstanceGetterInheritedFooMethod with MethodFoo {
+ e1;
+ int get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_FIELD_AND_METHOD
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ConflictStaticInstanceImplicitValues {
+ e1;
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.VALUES_DECLARATION_IN_ENUM
+ // [cfe] Enums can't contain declarations of members with the name 'values'.
+}
+
+enum ConflictStaticInstanceEnumValue {
+ e1;
+//^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ int get e1 => 42;
+ // ^
+ // [cfe] 'e1' is already declared in this scope.
+}
+
+enum ConflictEnumValueInheritedIndex {
+ index;
+//^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+// [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ConflictEnumValueInheritedToString {
+ toString;
+//^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+// [cfe] 'toString' is already declared in this scope.
+}
+
+enum ConflictEnumValueImplicitValues {
+ values;
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.VALUES_DECLARATION_IN_ENUM
+// [cfe] unspecified
+}
+
+enum ConflictEnumValueInheritedFoo with MethodFoo {
+ foo;
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+// [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ConflictClassGetterSetterTypeInstance {
+ e1;
+ num get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
+ // [cfe] The type 'num' of the getter 'ConflictClassGetterSetterTypeInstance.foo' is not a subtype of the type 'int' of the setter 'ConflictClassGetterSetterTypeInstance.foo'.
+
+ // Type of setter parameter must be subtype of type of getter.
+ void set foo(int _) {}
+}
+
+enum ConflictClassGetterSetterTypeStatic {
+ e1;
+ static num get foo => 42;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
+ // [cfe] The type 'num' of the getter 'ConflictClassGetterSetterTypeStatic.foo' is not a subtype of the type 'int' of the setter 'ConflictClassGetterSetterTypeStatic.foo'.
+
+ // Type of setter parameter must be subtype of type of getter.
+ static void set foo(int _) {}
+}
+
+enum NoConflictClassEnumValueStaticSetter {
+ e1;
+
+ static void set e1(NoConflictClassEnumValueStaticSetter _) {}
+}
+
+enum ConflictClassEnumValueStaticSetterType {
+ e1;
+//^^
+// [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
+// [cfe] The type 'ConflictClassEnumValueStaticSetterType' of the getter 'ConflictClassEnumValueStaticSetterType.e1' is not a subtype of the type 'int' of the setter 'ConflictClassEnumValueStaticSetterType.e1'.
+
+ // Type of setter parameter must be subtype of type of getter.
+ static void set e1(int _) {}
+}
+
+enum ConflictTypeParameterMember<foo> {
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+ e1;
+ int get foo => 42;
+ // ^
+ // [cfe] Conflicts with type variable 'foo'.
+}
+
+enum ConflictTypeParameterValues<values> {
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+ // [cfe] unspecified
+ e1;
+}
+
+enum ConflictTypeParameterEnumValue<e1> {
+ // ^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+ // [cfe] unspecified
+ e1;
+//^^
+// [cfe] unspecified
+}
+
+enum ConflictTypeParameters<T, T> {
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+ // [cfe] A type variable can't have the same name as another.
+ e1;
+}
+
+enum ConflictClassTypeParameter<ConflictClassTypeParameter> {
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
+ // [cfe] A type variable can't have the same name as its enclosing declaration.
+ e1;
+}
+
+// "If you define an instance member named $m$,
+// and your superclass has an instance member of the same name,
+// they override each other."
+
+enum OverrideInheritedMemberOverride with MethodFoo {
+ e1;
+ int foo(int x) => x; // super.foo is nullary.
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+ // [cfe] The method 'OverrideInheritedMemberOverride.foo' has more required arguments than those of overridden method '_Enum with MethodFoo.foo'.
+}
+
+enum OverrideInheritedMemberDifferentType with GetFoo {
+ e1;
+ int foo(int x) => x;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_METHOD_AND_FIELD
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum ImplementInheritedMemberDifferentType implements GetFoo {
+ e1;
+ int foo(int x) => x;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_METHOD_AND_FIELD
+ // [cfe] unspecified
+}
+
+enum OverrideInheritedParameterTypeOverride with SetFoo {
+ e1;
+ void set foo(Never n) {} // Invalid parameter override.
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+ // ^
+ // [cfe] The parameter 'n' of the method 'OverrideInheritedParameterTypeOverride.foo' has type 'Never', which does not match the corresponding type, 'int', in the overridden method, '_Enum with SetFoo.foo'.
+}
+
+// "Setters, getters and operators never have
+// optional parameters of any kind"
+
+enum DeclareOperatorOptional {
+ e1;
+ int operator+([int? x]) => x ?? 0;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
+ // ^
+ // [cfe] An operator can't have optional parameters.
+}
+
+enum DeclareSetterOptional {
+ e1;
+ void set foo([int? x]) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER
+ // ^
+ // [cfe] A setter should have exactly one formal parameter.
+}
+
+// "The identifier of a named constructor cannot be the same as
+// the basename of a static member declared in the same class"
+
+enum ConflictConstructorNameStatic {
+ e1.foo();
+ const ConflictConstructorNameStatic.foo();
+ // ^
+ // [cfe] Conflicts with member 'foo'.
+ // [analyzer] unspecified
+ static int get foo => 42;
+ // ^^^
+ // [analyzer] unspecified
+ // [cfe] Conflicts with constructor 'ConflictConstructorNameStatic.foo'.
+}
+
+enum ConflictConstructorNameStaticEnumValue {
+ e1.e1();
+//^^
+// [analyzer] unspecified
+// [cfe] Conflicts with constructor 'ConflictConstructorNameStaticEnumValue.e1'.
+ const ConflictConstructorNameStaticEnumValue.e1();
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] Conflicts with member 'e1'.
+}
+
+// "It is an error if a member has the same name as its enclosing class"
+
+enum ConflictClassStatic {
+ e1;
+//^
+// [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+ static int ConflictClassStatic() => 37;
+//^^^^^^
+// [analyzer] SYNTACTIC_ERROR.STATIC_CONSTRUCTOR
+// [cfe] Constructors can't be static.
+// ^^^
+// [analyzer] SYNTACTIC_ERROR.CONSTRUCTOR_WITH_RETURN_TYPE
+// [cfe] Constructors can't have a return type.
+// ^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR
+// [cfe] Generative enum constructors must be marked as 'const'.
+// ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+// ^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_OF_INVALID_TYPE
+// [cfe] Constructors can't have a return type.
+}
+
+enum ConflictClassInstance {
+ e1;
+//^
+// [cfe] Cannot invoke a non-'const' constructor where a const expression is expected.
+ int ConflictClassInstance() => 37;
+//^^^
+// [analyzer] SYNTACTIC_ERROR.CONSTRUCTOR_WITH_RETURN_TYPE
+// [cfe] Constructors can't have a return type.
+// ^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR
+// [cfe] Generative enum constructors must be marked as 'const'.
+// ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_IN_GENERATIVE_CONSTRUCTOR
+// ^^
+// [analyzer] COMPILE_TIME_ERROR.RETURN_OF_INVALID_TYPE
+// [cfe] Constructors can't have a return type.
+}
+
+enum ConflictClassEnumValue {
+ ConflictClassEnumValue;
+//^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING
+// [cfe] Name of enum constant 'ConflictClassEnumValue' can't be the same as the enum's own name.
+}
+
+// Has conflict with implicitly inserted `values` member.
+enum values {
+ // ^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ e1;
+}
+
+// "It is an error if a concrete class does not implement some member
+// of its interface, and there is no non-trivial \code{noSuchMethod}"
+
+enum UnimplementedInterface {
+ // ^^^^^^^^^^^^^^^^^^^^^^
+ // [cfe] The non-abstract class 'UnimplementedInterface' is missing implementations for these members:
+ e1;
+ int foo();
+//^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.ENUM_WITH_ABSTRACT_MEMBER
+}
+
+enum UnimplementedInterfaceInherited implements MethodFoo {
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
+ // [cfe] The non-abstract class 'UnimplementedInterfaceInherited' is missing implementations for these members:
+ e1;
+}
+
+enum ImplementedInterface with MethodFoo {
+ e1;
+ int foo(); // Abstract members are allowed.
+}
+
+enum ImplementedInterfaceNSM {
+ e1;
+ int foo(); // Abstract members are allowed.
+ dynamic noSuchMethod(i) => 42;
+}
+
+// Primitive Equality/HashCode.
+// Enums must not override `==` or `hashCode`.
+
+enum OverridesEquals {
+ e1;
+
+ bool operator==(Object other) => identical(e1, other);
+ // ^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+enum OverridesHashCode {
+ e1;
+
+ int get hashCode => 42;
+ // ^^^^^^^^
+ // [cfe] unspecified
+ // [analyzer] unspecified
+}
+
+// Invalid syntax that the compiled *should* recover from.
+abstract enum CannotBeAbstract {
+// [error column 1, length 8]
+// [analyzer] SYNTACTIC_ERROR.EXTRANEOUS_MODIFIER
+// [cfe] Can't have modifier 'abstract' here.
+ e1;
+}
+
+// Cannot reference generative constructors of enum classes.
+// Never allowed to reference by ClassName[.name],
+// only implicitly in value declarations and `this`[.name] in
+// redirecting generative constructors.
+// All ClassName[.name] references are errors.
+enum NoConstructorCalls {
+ e1(42),
+ e2.ignore(NoConstructorCalls(1)),
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enums can't be instantiated.
+ ;
+
+ final int x;
+
+ const NoConstructorCalls(this.x);
+ const NoConstructorCalls.ignore(dynamic _) : x = 0;
+
+ // Only valid use, as target of redirecting generative constructor.
+ const NoConstructorCalls.redirect() : this(1);
+ const NoConstructorCalls.redirectNamed() : this.ignore(0);
+
+ const NoConstructorCalls.invalidRedirect()
+ : this.ignore(NoConstructorCalls(1));
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // ^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_CONSTANT
+ // [cfe] Enums can't be instantiated.
+
+ // Generative constructors must be const.
+ NoConstructorCalls.notConst(this.x);
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONST_GENERATIVE_ENUM_CONSTRUCTOR
+// [cfe] Generative enum constructors must be marked as 'const'.
+
+ // As usual, redirecting generative constructors must redirect to
+ // generative constructors.
+ const NoConstructorCalls.badRedirect() : this.factory();
+ // ^
+ // [cfe] Final field 'x' is not initialized by this constructor.
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR
+ // [cfe] Couldn't find constructor 'NoConstructorCalls.factory'.
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.REDIRECT_TO_NON_CONST_CONSTRUCTOR
+
+ factory NoConstructorCalls.factory() => e1; // Valid.
+
+ // Cannot reference generative constructors from factory constructors.
+ factory NoConstructorCalls.badFactory() => NoConstructorCalls(2);
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enums can't be instantiated.
+
+ factory NoConstructorCalls.badFactoryRedirect(int x) = NoConstructorCalls;
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enum factory constructors can't redirect to generative constructors.
+
+ static const NoConstructorCalls e3 = NoConstructorCalls(3);
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enums can't be instantiated.
+
+ static void uses() {
+ Function f = NoConstructorCalls.new; // No tearoffs.
+ // ^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // ^
+ // [cfe] Enum constructors can't be torn off.
+
+ Function g = NoConstructorCalls.ignore; // No tearoffs.
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // ^
+ // [cfe] Enum constructors can't be torn off.
+
+ const c1 = NoConstructorCalls(0);
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enums can't be instantiated.
+
+ var v1 = new NoConstructorCalls(0);
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR
+ // [cfe] Enums can't be instantiated.
+ }
+}
+
+enum DeclaresInstanceValues {
+ e1;
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.VALUES_DECLARATION_IN_ENUM
+ // [cfe] Enums can't contain declarations of members with the name 'values'.
+}
+
+enum DeclaresStaticValues {
+ e1;
+ static int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.VALUES_DECLARATION_IN_ENUM
+ // [cfe] Enums can't contain declarations of members with the name 'values'.
+}
+
+enum InheritsValues with ValuesGetter {
+ // ^^^^^^^^^^^^^^
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_INHERITANCE
+ e1;
+}
+
+enum ImplementsValues implements ValuesGetter {
+ // ^^^^^^^^^^^^^^^^
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_INHERITANCE
+ e1;
+
+ noSuchMethod(i) => 42;
+}
+
+enum DeclaresInstanceIndex {
+ e1;
+ int get index => 42;
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+enum DeclaresStaticIndex {
+ e1;
+ static int get index => 42; // Conflicts with inherited instance member.
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_STATIC_AND_INSTANCE
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+enum InheritsIndex with IndexGetter {
+ // ^^^^^^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+ e1;
+}
+
+// No problem, implementation is not overridden.
+enum ImplementsIndex implements IndexGetter {
+ e1;
+}
+
+enum DeclaresNeverIndex {
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_IMPLEMENTATION_OVERRIDE
+ // [cfe] The implementation of 'index' in the non-abstract class 'DeclaresNeverIndex' does not conform to its interface.
+ e1;
+
+ Never get index;
+}
+
+enum ImplementsNeverIndex {
+ e1;
+
+ Never get index => throw "Never!";
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+enum NSMImplementsNeverIndex implements NeverIndexGetter {
+ // ^^^^^^
+ // [analyzer] unspecified
+ // [cfe] The implementation of 'index' in the non-abstract class 'NSMImplementsNeverIndex' does not conform to its interface.
+ e1;
+
+ noSuchMethod(i) => throw "Never!";
+}
+
+// Cannot have cyclic references between constants.
+enum CyclicReference {
+// ^
+// [cfe] Constant evaluation error:
+ e1(e2),
+//^
+// [cfe] Constant evaluation error:
+// ^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
+ e2(e1);
+ // ^^
+ // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
+ final CyclicReference other;
+ const CyclicReference(this.other);
+}
+
+// Since `values` contains `e1`,
+// we can't have a reference in the other direction.
+enum CyclicReferenceValues {
+// ^
+// [cfe] Constant evaluation error:
+ e1(values);
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
+ final List<CyclicReferenceValues> list;
+ const CyclicReferenceValues(this.list);
+}
+
+void main() {}
diff --git a/tests/language/enum/enhanced_enums_subtype_error_test.dart b/tests/language/enum/enhanced_enums_subtype_error_test.dart
new file mode 100644
index 0000000..c34d6b6
--- /dev/null
+++ b/tests/language/enum/enhanced_enums_subtype_error_test.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=enhanced-enums
+
+// Test errors required by new enhanced enum syntax.
+
+// Classes which implement `Enum`, but are not `enum` declarations,
+// have extra requirements.
+// Such a class is assumed to be either an interface intended to be
+// implemented by an `enum` declaration,
+// or a mixin intended to be mixed into an `enum` declaration.
+// As such, we enforce restrictions which would definitely make
+// that `enum` declaration invalid.
+//
+// * Such a class cannot be non-abstract.
+// * It cannot implement `index`, `hashCode`, `==` or `values`.
+
+class NonAbstract implements Enum {
+ // ^
+ // [cfe] Non-abstract class 'NonAbstract' has 'Enum' as a superinterface.
+ // ^^^^
+ // [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_DISALLOWED_TYPE
+
+ int get index => 42;
+}
+
+// Cannot contain a `values` member
+abstract class AbstractImplementsWithValues implements Enum {
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_DECLARATION
+ // [cfe] 'AbstractImplementsWithValues' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.
+}
+
+abstract class AbstractExtendsWithValues extends Enum {
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_DECLARATION
+ // [cfe] 'AbstractExtendsWithValues' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.
+}
+
+abstract class AbstractImplementsWithIndex implements Enum {
+ int get index => 42;
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+abstract class AbstractExtendsWithIndex extends Enum {
+ int get index => 42;
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+mixin MixinWithIndex on Enum {
+ int get index => 42;
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+mixin MixinWithIndex2 implements Enum {
+ int get index => 42;
+ // ^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_NON_ABSTRACT_ENUM_INDEX
+ // [cfe] unspecified
+}
+
+mixin MixinWithValues on Enum {
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_DECLARATION
+ // [cfe] 'MixinWithValues' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.
+}
+
+mixin MixinWithValues2 implements Enum {
+ int get values => 42;
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ENUM_VALUES_DECLARATION
+ // [cfe] 'MixinWithValues2' has 'Enum' as a superinterface and can't contain non-static member with name 'values'.
+}
+
+// Can't implement Enum and declare hashCode/==.
+abstract class ClassWithEquals implements Enum {
+ bool operator ==(Object other) => true;
+ // ^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+mixin MixinWithEquals implements Enum {
+ bool operator ==(Object other) => true;
+ // ^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+abstract class ClassWithHashCode implements Enum {
+ int get hashCode => 0;
+ // ^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+mixin MixinWithHashCode implements Enum {
+ int get hashCode => 0;
+ // ^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+abstract class SuperclassWithEquals {
+ bool operator ==(Object other) => true;
+}
+
+abstract class SuperclassWithHashCode {
+ int get hashCode => 0;
+}
+
+// Can't implement `Enum` and inherit concrete hashCode/==.
+abstract class ClassSuperEquals extends SuperclassWithEquals implements Enum {
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+abstract class ClassSuperHash extends SuperclassWithHashCode implements Enum {
+ // ^^^^^^^^^^^^^^
+ // [analyzer] unspecified
+ // [cfe] unspecified
+}
+
+// No class can implement an actual enum.
+
+abstract class ExtendsEnum extends MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // [cfe] The superclass, 'MyEnum', has no unnamed constructor that takes no arguments.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.EXTENDS_NON_CLASS
+}
+
+abstract class ImplementsEnum implements MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
+}
+
+abstract class MixesInEnum with MyEnum { // It's not a mixin!
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // [cfe] Can't use 'MyEnum' as a mixin because it has constructors.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.MIXIN_OF_NON_CLASS
+}
+
+mixin MixinImplementsEnum implements MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
+}
+
+mixin MixinOnEnum on MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE
+}
+
+enum EnumImplementsEnum implements MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
+ e1;
+}
+
+enum EnumMixesInEnum with MyEnum {
+ // ^
+ // [cfe] 'MyEnum' is an enum and can't be extended or implemented.
+ // [cfe] Can't use 'MyEnum' as a mixin because it has constructors.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.MIXIN_OF_NON_CLASS
+ e1;
+}
+
+void main() {}
+
+enum MyEnum {
+ e1;
+}
diff --git a/tools/VERSION b/tools/VERSION
index 7ca1bae..e3ebffd 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 127
+PRERELEASE 128
PRERELEASE_PATCH 0
\ No newline at end of file