Here’s a comment I added to https://github.com/lampepfl/dotty/pull/4028
So, I am trying to summarize here:
Why not keep value classes?
- The boxing model trips people up and can get in the way of high-performance code (in particular
because value classes cannot be stored in arrays) - The boxing model has surprisingly nasty consequences for code generation, including issues
that are still not fixed in any Scala compiler (#1905) - The limitations are hard to remember and a bit ad hoc.
What functionality do value classes provide?
- A low-cost implementation of some functionality in terms of some other type
- A way to add extension methods
- (In the future, once we can support multiple parameters) A way to do structs
Opaque types address (1), with some caveats
- They can currently not be toplevel
- They require sometimes a bit more code than value classes for the same functionality
- They require some concept shifts that are non-trivial to implement (e.g. companions of opaque types, with special visibility)
For (2) we have a separate extension method proposal which is syntactically nicer than implicit value classes.
(3) is currently not possible on the JVM, non-sensical on JS, and addressed with @struct on Native. (3) might be possible with Valhalla in the future.
One idea we should further explore before deciding is to come back to the original proposal of “unboxed wrapper types” Pre-SIP: Unboxed wrapper types. I.e. define a lightweight way to define classes that, like opaque types, do not box, but that can take multiple parameters if the platform allows it. A possible syntax could be
inline class C(x_1: T_1, ..., x_n: T_n) /* no parents allowed */ {
def ...
def ...
/* no other members allowed */
}
On today’s JVM, n = 1. inline
classes defined that way are always represented as their underlying type. Their parent is Any
but they cannot override any of its methods. The potential advantages that I can see relative to opaque types are:
- sometimes less boilerplate
- can do extension methods as well when combined with
implicit
. So it would then be a separate decision whether we want to replaceimplicit inline class
withextension
. - can express structs / multiparameter value classes.
I don’t know whether inline classes defined that way would map well to Valhalla’s value classes. Can somebody who knows the state of things in Valhalla give some insight here?
To expand on it a bit here: Originally, the SIP committee was against the Unboxed Wrapper Types proposal because the overlap with value classes seemed to great. The new development is that we are now prepared to phase out value classes altogether. This idea was not on the table when the proposal started but is gaining a lot of momentum now. So, if the question is how to replace value classes then it’s actually good if the new feature has a lot of overlap with the one it replaces because it will be more familiar, code will be easier to port, and so on.