(The Scala Org aims to release Scala 3 by the end of fall 2020. We are about 15 employees (some of whom work part-time), spread in 4 organisations (+ active community members), focusing on finalising 52 essential projects in 6 months. As of today, project leads will publish the road-maps under the category “Scala 3 release projects” to share with you what is to be expected and hopefully get your advice & contributions as well. All the projects’ road-maps come after an extensive feedback gathering, rounds of discussion, and involvement of major stakeholders, we now need the community to help push this effort over the line. Your collaboration is highly appreciated, thank you in advance!)
The Scala Center team is working on improvements to the enumerations feature before the release of Scala 3, with these main goals in mind:
- To improve compatibility of enumerations with Java serialisation framework, and Java’s enum APIs when an enumeration extends
java.lang.Enum
. - To provide consistent API’s even as enum definitions grow beyond simple enumerations.
- To improve intuition behind the desugaring of enum definitions.
Milestone 1: Improve support for Java APIs
- As it stands in the
0.26.0-RC1
release, if a singleton enum value does not extendjava.lang.Enum
then it will not remain singleton if it is deserialized using the Java serialization framework. This can be remedied by implementingreadResolve
to replace the serialized object by one of the known constants. - The
java.lang.Enum
API depends heavily on runtime checking of superclasses of enum values, so it is unsafe to extendjava.lang.Enum
by more than 2 subclasses deep. When not using migration mode in the compiler, we will restrict extension ofjava.lang.Enum
to only from traits or the enum syntax, as it is done in Java. - Enumerations extending
java.lang.Enum
will be restricted to only be defined in a static object, this is because the Java Language Specification forbids enums which are inner classes. - The
values
array method on the companion object of an enumeration will be sorted by ordinal.
Milestone 2: custom toString for enum
- As it stands in the
0.26.0-RC1
release, a singleton enum value always overridestoString
to be equivalent to the identifier of the enum case. This prevents customisation oftoString
by the user. We will provide a mechanism for the user to overridetoString
and preserve the accuracy of APIs such asvalueOf
which looks up values by the string of their identifier.
Milestone 3: Simplification of APIs
- We will remove
scala.runtime.EnumValues
in favour of implementing caching and lookup logic directly in the companion object of an enum. - We will likely remove the
scala.Enum
trait while still providing dynamic lookup of the name and ordinal of each enum case. This will make it simpler to extendjava.lang.Enum
which guarantees your enumeration has only singleton cases. - We will standardise the representation of Java style enums in the TASTy format so that it is independent of the compiler.
Milestone 4: Improve Intuition for Enum Desugaring
- The companion of an enumeration will define public lookup methods (such as
values
orvalueOf
) exactly when the enumeration only defines singleton values. It does not matter if the enumeration carries type parameters. If an enum case with a constructor is added, these lookup methods will no longer be generated. - Enum cases that do not explicitly provide type parameters will copy the variances of type parameters of the enum that defines them. If an invariant type parameter is required by the constructor, the user will be warned to explicitly provide type parameters for the enum case
- We will experiment with improving type inference for enumerations, allowing the
apply
method of enum case companions to give the most precise type.
Acknowledgements
Thank you to Guillaume Raffin for contributing the checks that enforce enum syntax for enumerations extending java.lang.Enum
.
Major Changes to the Original SIP
A new change was prompted by the need for an appropriate API to retrieve the identifier of an enum value as a String, where the implementation is restricted to the compiler. In general, it is not a good choice to add a name
method, such as in java.lang.Enum
, to all enums because that is likely to collide with a name
field of a class enum case. To avoid that likely collision, the method name enumLabel
was chosen as an instance method for an enum class. As a public API, enumLabel
may be adding extra burden when we already have the similar method productPrefix
. enumLabel
was thought to be more friendly to beginners as a teaching tool, however the need to avoid collisions generates a similarly cryptic name. An alternative is to generate a public method on the companion such as def labelOf(value: E): String
where E
is an enum type.
As with any of our announcements, we invite your feedback and discussion, as these changes will have to be reviewed by the SIP committee.