Skip to content

Commit 7162133

Browse files
bishaboshaWojciechMazur
authored andcommitted
remove implementation details from enum spec
[Cherry-picked a7d1e33]
1 parent e521582 commit 7162133

File tree

1 file changed

+62
-95
lines changed

1 file changed

+62
-95
lines changed

Diff for: docs/_spec/05-classes-and-objects.md

+62-95
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ Very much like a concrete class definition, an object definition may still conta
904904
<!-- TODO: Agree with NTs of rest of spec -->
905905
```ebnf
906906
TmplDef ::= ‘enum’ EnumDef
907-
EnumDef ::= id ClassConstr [‘extends’ [ConstrApps]] EnumBody
907+
EnumDef ::= id ClassConstr [‘extends’ ConstrApps] EnumBody
908908
EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
909909
EnumStat ::= TemplateStat
910910
| {Annotation [nl]} {Modifier} EnumCase
@@ -925,18 +925,15 @@ First, some terminology and notational conventions:
925925
- We use `<...>` for syntactic constructs that in some circumstances might be empty.
926926
For instance, `<value-params>` represents one or more parameter lists `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)` or nothing at all.
927927
- Enum classes fall into two categories:
928-
- _parameterized_ enum classes have at least one of the following:
929-
- a type parameter section, denoted as `[´\mathit{tps}\,´]`;
930-
- one or more (possibly empty) parameter sections, denoted as `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)`.
931-
- _unparameterized_ enum classes have no type parameter sections and no parameter sections.
928+
- _parameterized_ enum classes have at least one or more (possibly empty) term parameter clauses, denoted as `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)`.
929+
- _unparameterized_ enum classes have no term parameter clauses, but may optionally have a type parameter clause, denoted as `[´\mathit{tps}\,´]`.
932930
- Enum cases fall into three categories:
933-
934-
- _Class cases_ are those cases that are parameterized, either with a type parameter section `[´\mathit{tps}\,´]` or with one or more (possibly empty) parameter sections `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)`.
935-
- _Simple cases_ are cases of an unparameterized enum that have neither parameters nor an extends clause or body.
931+
- _Class enum cases_ are those cases that possibly have a type parameter clause `[´\mathit{tps}\,´]`, and necessarily have one or more (possibly empty) parameter clauses `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)`.
932+
- _Simple enum cases_ are those cases that have no parameter clauses and no extends clause.
936933
That is, they consist of a name only.
937-
- _Value cases_ are all cases that do not have a parameter section but that do have a (possibly generated) `extends` clause and/or a body.
934+
- _Value enum cases_ are those cases that have no parameter clauses but that do have a (possibly generated) `extends` clause.
938935

939-
- Simple cases and value cases are collectively called _singleton cases_.
936+
- Simple enum cases and value enum cases are collectively called _singleton enum cases_.
940937

941938
###### Example
942939

@@ -970,13 +967,11 @@ enum Option[+T]:
970967
### Lowering of Enum Definitions
971968

972969
###### Summary
973-
An enum class is represented as a `sealed` class that extends the `scala.reflect.Enum` trait.
970+
An enum class is represented as a `sealed abstract` class that extends the `scala.reflect.Enum` trait.
974971

975972
Enum cases are represented as follows:
976-
- a class case is mapped to a `case class`,
977-
- a singleton case is mapped to a `val` definition, where
978-
- Simple cases all share a single implementation class.
979-
- Value cases will each be implemented by a unique class.
973+
- a class enum case is mapped to a `case class` member of enum class' companion object,
974+
- a singleton enum case is mapped to a `val` member of the enum class' companion object, implemented by a local class definition which may be shared between cases.
980975

981976
###### Precise rules
982977
The `scala.reflect.Enum` trait defines a single public method, `ordinal`:
@@ -989,106 +984,119 @@ transparent trait Enum extends Any, Product, Serializable:
989984
```
990985
There are nine desugaring rules.
991986
Rule (1) desugars enum definitions.
992-
Rules (2) and (3) desugar simple cases.
993-
Rules (4) to (6) define `extends` clauses for cases that are missing them.
994-
Rules (7) to (9) define how such cases with `extends` clauses map into `case class`es or `val`s.
987+
Rule (2) desugars cases of comma-separated names to simple enum cases.
988+
Rules (3) to (7) desugar inferrable details of enum cases.
989+
Rules (8) and (9) define how fully-desugared enum cases map into `case class`es or `val`s.
990+
Explicit `extends` clauses must be provided in the following cases, where rules (2) to (6) do not apply:
991+
- any enum case of a parameterized enum,
992+
- any singleton enum case of an unparameterized enum with non-variant type parameters,
993+
- any class enum case of an enum with type parameters, where the case also has type parameters.
995994

996995
1. An `enum` definition
997996
```scala
998-
enum ´E´ ... { <defs> <cases> }
997+
enum ´E´ <type-params> <value-params> { <defs> <cases> }
999998
```
1000999
expands to a `sealed abstract` class that extends the `scala.reflect.Enum` trait and an associated companion object that contains the defined cases, expanded according to rules (2 - 8).
10011000
The enum class starts with a compiler-generated import that imports the names `<caseIds>` of all cases so that they can be used without prefix in the class.
10021001
```scala
1003-
sealed abstract class ´E´ ... extends <parents> with scala.reflect.Enum {
1004-
import ´E´.{ <caseIds> }
1005-
<defs>
1002+
sealed abstract class ´E´ <type-params> <value-params>
1003+
extends <parents> with scala.reflect.Enum {
1004+
import ´E´.{ <caseIds> }
1005+
<defs>
10061006
}
10071007
object ´E´ { <cases> }
10081008
```
10091009

1010-
2. A singleton case consisting of a comma-separated list of enum names
1010+
2. A simple enum case consisting of a comma-separated list of names
10111011
```scala
10121012
case ´C_1´, ..., ´C_n´
10131013
```
1014-
expands to
1014+
expands to the following simple enum cases
10151015
```scala
10161016
case ´C_1´; ...; case ´C_n´
10171017
```
10181018
Any modifiers or annotations on the original case extend to all expanded cases.
1019-
This result is then further rewritten by either (3 or 4).
1019+
<p>This result is then further rewritten by either (3 or 4).</p>
10201020

1021-
3. A singleton case without an extends clause
1021+
3. A simple enum case `´C´` of an unparameterized enum `´E´` without type parameters
10221022
```scala
10231023
case ´C´
10241024
```
1025-
of an unparameterized enum `´E´` expands to the following simple enum case in `´E´`'s companion object:
1025+
expands to the following value enum case:
10261026
```scala
1027-
val ´C´ = $new(n, "C")
1027+
case ´C´ extends ´E´
10281028
```
1029-
Here, `$new` is a private method that creates an instance of ´E´ (see below).
1029+
This result is then further rewritten with rule (8).
10301030

1031-
4. A singleton case without an extends clause
1031+
4. A simple enum case `´C´` of an unparameterized enum `´E´[´\mathit{tps}´]` with type parameters
10321032
```scala
10331033
case ´C´
10341034
```
1035-
of an enum `´E´` with type parameters
1035+
where `´\mathit{tps}´` are of the following form
10361036
```scala
10371037
´\mathit{v}_1´ ´T_1´ >: ´L_1´ <: ´U_1´ , ... , ´\mathit{v}_n´ ´T_n´ >: ´L_n´ <: ´U_n´ (n > 0)
10381038
```
1039-
where each of the variances `´\mathit{v}_i´` is either `'+'` or `'-'`, expands to the following value enum case:
1039+
and where each of the variances `´\mathit{v}_i´` is either `'+'` or `'-'`, expands to the following value enum case:
10401040
```scala
10411041
case ´C´ extends ´E´[´B_1´, ..., ´B_n´]
10421042
```
10431043
where `´B_i´` is `´L_i´` if `´\mathit{v}_i´ = '+'` and `´U_i´` if `´\mathit{v}_i´ = '-'`.
1044-
This result is then further rewritten with rule (8).
1045-
**NOTE:** It is not permitted for enums with non-variant type parameters to have singleton cases without an extends clause.
1044+
<p>This result is then further rewritten with rule (8).</p>
10461045

1047-
5. A class case without an extends clause
1046+
5. A class enum case with type parameters, but without an extends clause
10481047
```scala
1049-
case ´C´ <type-params> <value-params>
1048+
case ´C´\mathit{tps}´](´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)
10501049
```
1051-
of an enum `´E´` that does not take type parameters expands to
1050+
of an unparameterized enum `´E´` without type parameters expands to
10521051
```scala
1053-
case ´C´ <type-params> <value-params> extends ´E´
1052+
case ´C´\mathit{tps}´](´\mathit{ps}_1\,´)...(´\mathit{ps}_n´) extends ´E´
10541053
```
10551054
This result is then further rewritten with rule (9).
10561055

1057-
6. If `´E´` is an enum with type parameters `´\mathit{tps}´`, a class case with neither type parameters nor an extends clause
1056+
6. A class enum case without type parameters or an extends clause
10581057
```scala
1059-
case ´C´ <value-params>
1058+
case ´C´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)
10601059
```
1061-
expands to
1060+
of an unparameterized enum `´E´[´\mathit{tps}´]` with type parameters expands to
10621061
```scala
1063-
case ´C´[´\mathit{tps}´] <value-params> extends ´E´[´\mathit{tps}´]
1062+
case ´C´(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´) extends ´E´[´\mathit{tps}´]
10641063
```
1065-
This result is then further rewritten with rule (9).
1066-
For class cases that have type parameters themselves, an extends clause needs to be given explicitly.
1067-
1064+
This result is then further rewritten with rule (7).
10681065

1069-
7. If `´E´` is an enum with type parameters `´\mathit{tps}´`, a class case without type parameters but with an extends clause
1066+
7. A class enum case without type parameters, but has an extends clause
10701067
```scala
1071-
case ´C´ <value-params> extends <parents>
1068+
case ´C´\mathit{ps}_1\,´)...(´\mathit{ps}_n´) extends <parents>
10721069
```
1073-
expands to
1070+
of an enum `´E´[´\mathit{tps}´]` with type parameters expands to
10741071
```scala
1075-
case ´C´[´\mathit{tps}´] <value-params> extends <parents>
1072+
case ´C´[´\mathit{tps}´]\mathit{ps}_1\,´)...(´\mathit{ps}_n´) extends <parents>
10761073
```
1077-
provided at least one of the parameters `´\mathit{tps}´` is mentioned in a parameter type in `<value-params>` or in a type argument in `<parents>`.
1074+
provided at least one of the parameters `´\mathit{tps}´` is mentioned in a parameter type in `(´\mathit{ps}_1\,´)...(´\mathit{ps}_n´)` or in a type argument in `<parents>`.
1075+
<br/><br/>
1076+
This result is then further rewritten with rule (9).
10781077

1079-
8. A value case
1078+
8. A singleton enum case
10801079
```scala
10811080
case ´C´ extends <parents>
10821081
```
10831082
expands to the following `val` definition in `´E´`'s companion object:
10841083
```scala
1085-
val ´C´ = new <parents> { <body>; def ordinal = ´\mathit{n}´ }
1084+
val ´C´ = $factory(_$ordinal = ´\mathit{n}´, $name = "C")
10861085
```
10871086
where `´\mathit{n}´` is the ordinal number of the case in the companion object, starting from 0.
1087+
`$factory` is a placeholder that expands its arguments into an expression that produces something equivalent to
1088+
a new instance of the following (possibly shared) anonymous class:
1089+
```scala
1090+
new <parents> {
1091+
def ordinal: Int = _$ordinal
1092+
override def toString: String = $name
1093+
}
1094+
```
10881095
The anonymous class also implements the abstract `Product` methods that it inherits from `Enum`.
1096+
<br/><br/>
10891097
**NOTE:** It is an error if a value case refers to a type parameter of `´E´` in a type argument within `<parents>`.
10901098

1091-
9. A class case
1099+
9. A class enum case
10921100
```scala
10931101
case ´C´ <type-params> <value-params> extends <parents>
10941102
```
@@ -1099,6 +1107,7 @@ Rules (7) to (9) define how such cases with `extends` clauses map into `case cla
10991107
}
11001108
```
11011109
where `´\mathit{n}´` is the ordinal number of the case in the companion object, starting from 0.
1110+
<br/><br/>
11021111
**NOTE:** It is an error if a class case refers to a type parameter of `´E´` in a parameter type in `<type-params>` or `<value-params>` or in a type argument of `<parents>`, unless that parameter is already a type parameter of the case, i.e. the parameter name is defined in `<type-params>`.
11031112

11041113
###### Superclass of an enum case
@@ -1131,34 +1140,6 @@ private def $new(_$ordinal: Int, $name: String) =
11311140
override def toString = $name
11321141
```
11331142

1134-
1135-
###### Example
1136-
1137-
Consider the more complex enumeration `Color`, consisting of value enum cases:
1138-
```scala
1139-
enum Color(val rgb: Int):
1140-
case Red extends Color(0xFF0000)
1141-
case Green extends Color(0x00FF00)
1142-
case Blue extends Color(0x0000FF)
1143-
```
1144-
1145-
The three value cases will expand as follows in the companion of `Color`:
1146-
1147-
```scala
1148-
val Red = new Color(0xFF0000):
1149-
def ordinal: Int = 0
1150-
override def productPrefix: String = "Red"
1151-
override def toString: String = "Red"
1152-
val Green = new Color(0x00FF00):
1153-
def ordinal: Int = 1
1154-
override def productPrefix: String = "Green"
1155-
override def toString: String = "Green"
1156-
val Blue = new Color(0x0000FF):
1157-
def ordinal: Int = 2
1158-
override def productPrefix: String = "Blue"
1159-
override def toString: String = "Blue"
1160-
```
1161-
11621143
### Widening of enum cases post-construction
11631144
The compiler-generated `apply` and `copy` methods of an class enum case
11641145
```scala
@@ -1176,20 +1157,6 @@ An enum `´E´` (possibly generic) that defines one or more singleton cases, and
11761157
It returns the singleton case value whose identifier is `name`.
11771158
- A method `values` which returns an `Array[´E'´]` of all singleton case values defined by `E`, in the order of their definitions.
11781159

1179-
### Factory method for simple enum cases
1180-
1181-
If an enum `´E´` contains at least one simple case, its companion object will define in addition:
1182-
1183-
- A private method `$new` which defines a new simple case value with given ordinal number and name.
1184-
This method can be thought as being defined as follows.
1185-
1186-
```scala
1187-
private def $new(_$ordinal: Int, $name: String): ´E´ with runtime.EnumValue
1188-
```
1189-
- `$new` returns a new instance of an anonymous class which implements the abstract `Product` methods that it inherits from `Enum`.
1190-
- if `´E´` inherits from `java.lang.Enum` the anonymous class does not override the `ordinal` or `toString` methods, as these are final in `java.lang.Enum`.
1191-
Additionally `productPrefix` will delegate to `this.name`.
1192-
11931160
### Translation of Java-compatible enums
11941161

11951162
A Java-compatible enum is an enum that extends `java.lang.Enum`.

0 commit comments

Comments
 (0)