Skip to content

Commit d90210c

Browse files
authored
Say that an enum constructor cannot use super-parameters. (#2145)
* Say that an enum constructor cannot use super-parameters.
1 parent f02a131 commit d90210c

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

accepted/future-releases/enhanced-enums/feature-specification.md

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Dart Enhanced Enum Classes
22

3-
Author: [email protected]<br>Version: 1.7<br>Tracking issue [#158](https://github.com/dart-lang/language/issues/158)
3+
Author: [email protected]<br>Version: 1.8<br>Tracking issue [#158](https://github.com/dart-lang/language/issues/158)
44

55
This is a formal specification for a language feature which allows `enum` declarations to declare classes with fields, methods and `const` constructors initializing those fields. Further, `enum` declarations can implement interfaces and apply mixins.
66

@@ -54,12 +54,16 @@ It is a **compile-time error** if the initializer list of a non-redirecting gene
5454

5555
_We will introduce the necessary super-invocation ourselves as an implementation detail. From the user’s perspective, they extend `Enum` which has no public constructors. We could allow `super()`, which would then be a constructor of `Enum`, but it's simpler to just disallow super invocations entirely._
5656

57+
It is a **compile-time error** if the argument list of a non-redirecting generative constructor includes a `super` parameter.
58+
59+
_Super parameters (a feature introduced in the same release as enhanced enums) implicitly adds arguments to the `super` constructor invocation of a non-redirecting generative constructor, and such enum constructors do not have a known superclass constructor expecting such arguments._
60+
5761
It is a **compile-time error** to refer to a declared or default generative constructor of an `enum` declaration in any way, other than:
5862

59-
* As the target of a redirecting generative constructor of the same `enum` declaration, or
60-
* Implicitly in the enum value declarations of the same `enum`.
63+
* As the target of a redirecting generative constructor of the same `enum` declaration (`: this(...);`/`: this.targetName(...);`), or
64+
* Implicitly in the enum value declarations of the same `enum` (`enumValueName(args)`/`enumValueName.targetName(args)`).
6165

62-
_No-one is allowed to invoke a generative constructor and create another instance of the `enum`.
66+
_No-one is allowed to invoke a generative constructor and create an instance of the `enum` other than the enumerated enum values.
6367
That also means that a redirecting *factory* constructor cannot redirect to a generative constructor of an `enum`,
6468
and therefore no factory constructor of an `enum` declaration can be `const`, because a `const` factory constructor must redirect to a generative constructor._
6569

@@ -81,13 +85,13 @@ We intend to (at least pretend to) let `enum` classes extend `Enum`, and let mix
8185

8286
This all makes it look as if `Enum` would be a valid superclass for the mixin applications and methods of the enhanced `enum` class.
8387

84-
The semantics of such an enum declaration, *E*, is defined as introducing a (semantic) *class*, *C*, just like a similar `class` declaration.
88+
The semantics of such an enum declaration, *E* with name *N*, is defined as introducing a (semantic) *class*, *C*, just like a similar `class` declaration.
8589

86-
* **Name**: The name of the class *C* and its implicit interface is the name of the `enum` declaration.
90+
* **Name**: The name of the class *C* and its implicit interface is the name *N* of the `enum` declaration.
8791

8892
* **Superclass**: The superclass of *C* is an implementation-specific built-in class *`EnumImpl`*, with the mixins declared by *E* applied. _(The `EnumImpl` class may be the `Enum` class itself or it may be another class which extends or implements `Enum`, but as seen from a non-platform library the interface of *`EnumImpl`* is the same as that of `Enum`, and its methods work as specified for `Enum` )_
8993

90-
* If *E* is declared as `enum Name with Mixin1, Mixin2` then the superclass of *C* is the mixin application <Code>*EnumImpl* with Mixin1, Mixin2</code>.
94+
* If *E* is declared as <code>enum *N* with *Mixin1*, *Mixin2* …</code> then the superclass of *C* is the mixin application <Code>*EnumImpl* with *Mixin1*, *Mixin2*</code>.
9195

9296
It’s a **compile-time error** if such a mixin application introduces any instance variables. _We need to be able to call an implementation specific superclass `const` constructor of `Enum`, and a mixin application of a mixin with a field does not make its forwarding constructor `const`. Currently that’s the only restriction, but if we add further restrictions on mixin applications having `const` forwarding constructors, those should also apply here._
9397

@@ -97,49 +101,49 @@ The semantics of such an enum declaration, *E*, is defined as introducing a (sem
97101

98102
- **Declared members**: For each member declaration of the `enum` declaration *E*, the same member is added to the class *C*. This includes constructors (which must be `const` generative or non-`const` factory constructors.)
99103

100-
- **Default constructor**: If no generative constructors were declared, and no unnamed factory constructor was added,
104+
- **Default constructor**: If no generative constructors were declared, and also no factory constructor with name *N* was declared,
101105
a default generative constructor is added:
102106

103107
```dart
104108
const Name();
105109
```
106110

107-
_(This differs from the default constructor of a normal `class` declaration by being constant, and by being added even if a factory constructor is present. If no generative constructor is declared, and the unnamed constructor is taken by a factory constructor, there is no way for the enum declaration to compile successfully, since the declaration must contain at least one enum value, and that enum value must refer to a generative constructor.)_
111+
_(This differs from the default constructor of a normal `class` declaration by being constant, and by being added even if a factory constructor is present. If no generative constructor is declared, and the unnamed constructor name is taken by a factory constructor, there is no way for the enum declaration to compile successfully, since the declaration must contain at least one enum value, and that enum value must refer to a generative constructor.)_
108112

109-
- **Enum values**: For each `<enumEntry>` with name `id` and index *i* in the comma-separated list of enum entries, a constant value is created, and a static constant variable named `id` is created in *C* with that value. All the constant values are associated, in some implementation dependent way, with
113+
- **Enum values**: For each `<enumEntry>` with name *id* and index *i* in the comma-separated list of enum entries, a constant value is created, and a static constant variable named *id* is created in *C* with that value. All the constant values are associated, in some implementation dependent way, with
110114

111-
- their name `id` as a string `"id"`,
115+
- their name *id* as a string `"id"`,
112116
- their index *i* as an `int`, and
113-
- their `enum` class’s name as a string, `"Name"`,
117+
- their `enum` class’s name as a string, <code>"*N*"</code>,
114118

115119
all of which are accessible to the `toString` and `index` member of `Enum`, and to the `EnumName.name` extension getter. The values are computed as by the following constant constructor invocations.
116120

117-
- `id` &mapsto; `const Name()` (no arguments, equivalent to empty argument list)
118-
- `id(args)` &mapsto; `const Name(args)`
119-
- `id<types>(args)` &mapsto; `const Name<types>(args)`
120-
- `id.named(args)` &mapsto; `const Name.named(args)`
121-
- `id<types>.named(args)` &mapsto; `const Name<types>.named(args)`
121+
- <code>*id*</code> &mapsto; <code>const *N*()</code> (no arguments, equivalent to empty argument list)
122+
- <code>*id*(*args*)</cide> &mapsto; <code>const *N*(*args*)</code>
123+
- <code>*id*<*types*>(*args*)</code> &mapsto; <code>const *N*<*types*>(*args*)</code>
124+
- <code>*id*.*named*(*args*)</code> &mapsto; <Code>const *N*.*named*(*args*)</code>
125+
- <code>*id*<*types*>.*named*(*args*)</code> &mapsto; <code>const *N*<*types*>.*named*(*args*)</code>
122126

123-
where `args` are considered as occurring in a `const` context, and it’s a **compile-time error** if they are then not compile-time constants.
127+
where *args* are considered as occurring in a `const` context, and it’s a **compile-time error** if they are then not compile-time constants.
124128

125129
The resulting constructor invocations are subject to type inference, using the empty context type. *This implies that inferred type arguments to the constructor invocation itself may depend on the types of the argument expressions of `args`.* The type of the constant variable is the static type of the resulting constant object creation expression.
126130

127131
The objects created here are *not canonicalized* like other constant object creations. _(In practice, the index value is considered part of the object, so no two objects will have the same state.)_
128132

129-
- **Static `values` list**: A static constant variable named `values` is added as by the declaration `static const List<Name> values = [id1, …, idn];`
130-
where `id1``idn` are the names of the enum entries of the `enum` declaration in source/index order.
131-
_If `Name` is generic, the `List<Name>` instantiates `Name` to its bounds._
133+
- **Static `values` list**: A static constant variable named `values` is added as by the declaration <code>static const List<*N*> values = [*id*<sub>1</sub>, …, *id*<sub>*n*</sub>];</code>
134+
where <code>*id*<sub>1<sub></code>…<code>*id*<sub>*n*</sub></code> are the names of the enum entries of the `enum` declaration in source/index order.
135+
_If *C* is a generic class (*E* is a generic enum), the <code>List<N></code> instantiates <code>*N*</code> to its bounds._
132136

133-
It's a **compile-time error** if an `enum` declaration declares or inherits a concrete member named `index` which overrides the `index` getter of the `Enum` class. _Such an inherited `index` member would necessarily have been introduced by a mixin application of the `enum` declaration._
137+
It's a **compile-time error** if an `enum` declaration declares or inherits a concrete member named `index` which overrides the `index` getter of the `Enum` class. _Such an inherited `index` member would necessarily have been introduced by a mixin application of the `enum` declaration._
134138

135-
It's a **compile-time error** if an `enum` declaration declares or inherits a concrete member named `hashCode` or `==` *(an `operator ==` declaration)* which overrides the `hashCode` getter or `==` operator of the `Object` class. (The `Enum` class does not override `hashCode` or `operator==` from `Object`). _This ensures that enum values can be used as switch statement case values, which is the main advantage of using an enum over just writing a normal class._
139+
It's a **compile-time error** if an `enum` declaration declares or inherits a concrete member named `hashCode` or `==` *(an `operator ==` declaration)* which overrides the `hashCode` getter or `==` operator of the `Object` class. (The `Enum` class does not override `hashCode` or `operator==` from `Object`). _This ensures that enum values can be used as switch statement case values, which is the main advantage of using an enum over just writing a normal class._
136140

137141
If the resulting class would have any naming conflicts, or other compile-time errors, the `enum` declaration is invalid and a compile-time error occurs. Such errors include, but are not limited to:
138142

139143
- Declaring or inheriting (from `Enum` or from a declared mixin or interface) any member with the same basename as an enum value which is not a static setter. _(The introduced static declarations would have a conflict.)_
140144
- Declaring or mixing in a member which is not a valid override of a super-interface member declaration, including the `runtimeType`, `noSuchMethod` and `toString` members of `Object`, or any members introduced by mixin applications.
141145
- Declaring or inheriting an member signature with no corresponding implementation. _(For example declaring an abstract `String toString([int optional])`, but not providing an implementation.)_
142-
- Declaring a generic `enum` which does not have a valid well-bounded instantiate-to-bounds result. _(The automatically introduced `static const List<EnumName> values` requires a well-bounded instantiate-to-bounds result)_.
146+
- Declaring a generic `enum` which does not have a valid well-bounded instantiate-to-bounds result. _(The automatically introduced <code>static const List<*N*> values</code> requires a well-bounded instantiate-to-bounds result)_.
143147
- Declaring a generic `enum` which does not have a regular-bounded instantiate-to-bounds result *and* that has an enum value declaration omitting the type arguments and not having arguments from which type arguments can be inferred. _(For example `enum EnumName<F extends C<F>> { foo; }` would introduce an implicit `static const foo = EnumName(0, "foo");` declaration where the constructor invocation requires a regular-bounded instantiate-to-bounds result)_.
144148
- Using a non-constant expression as an argument of an enum value declaration.
145149
- Declaring a static member and inheriting an instance member with the same base-name.
@@ -453,3 +457,4 @@ There is a chance that people will start using `enum` declarations to declare si
453457
1.5, 2021-12-07: Say that `index` and `toString` are inherited from the superclass, `values` is omitted if it would conflict. Rephrase specification in terms of defining a semantic class, not a syntactic one.
454458
1.6, 2022-01-27: Disallow overriding `index` or conflicting with `values`.
455459
1.7, 2022-02-16: Disallow overriding `operator==` and `hashCode` too.
460+
1.8, 2022-03-08: Make it explicit that an enum constructor cannot use the new super-parameters.

0 commit comments

Comments
 (0)