(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-RC1release, if a singleton enum value does not extendjava.lang.Enumthen it will not remain singleton if it is deserialized using the Java serialization framework. This can be remedied by implementingreadResolveto replace the serialized object by one of the known constants. - The
java.lang.EnumAPI depends heavily on runtime checking of superclasses of enum values, so it is unsafe to extendjava.lang.Enumby more than 2 subclasses deep. When not using migration mode in the compiler, we will restrict extension ofjava.lang.Enumto only from traits or the enum syntax, as it is done in Java. - Enumerations extending
java.lang.Enumwill be restricted to only be defined in a static object, this is because the Java Language Specification forbids enums which are inner classes. - The
valuesarray 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-RC1release, a singleton enum value always overridestoStringto be equivalent to the identifier of the enum case. This prevents customisation oftoStringby the user. We will provide a mechanism for the user to overridetoStringand preserve the accuracy of APIs such asvalueOfwhich looks up values by the string of their identifier.
Milestone 3: Simplification of APIs
- We will remove
scala.runtime.EnumValuesin favour of implementing caching and lookup logic directly in the companion object of an enum. - We will likely remove the
scala.Enumtrait while still providing dynamic lookup of the name and ordinal of each enum case. This will make it simpler to extendjava.lang.Enumwhich 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
valuesorvalueOf) 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
applymethod 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.
