Maybe the JVM improvements coming next year can save value classes, but otherwise let's go with something that favors guaranteed absence of boxing over convenience.
Implicit classes are the main beneficiary of value classes. Maybe we can just bake in the extends AnyVal performance optimization.
One big difference between value classes and opaque types (which I don't see mentioned in http://docs.scala-lang.org/sips/opaque-types.html) is that value classes can be top level, while it looks like opaque types are being designed not to be. (See also https://github.com/scala/scala-dev/issues/441 where top-level definitions are mentioned).
Also, when I asked @odersky about making implicit classes auto-extend AnyVal he said he didn't like that because it introduced it irregularity.
If we want to specialize "implicit class" to also be the only form of AnyVal-ness, then we should seriously consider adopting "extension methods" as a core part of the language, so that (opaque type aliases + extension methods) replace (implicit classes + value classes). That would really simplify Scala (as perceived if not in the core language spec).
Note that AnyVals can extend universal traits. Opaque type aliases cannot. Cf. ArrayOps for a particularly core example. I would personally be happy with dropping that capability from the language, but @odersky mentioned that universal traits came from very serious considerations and that, at least at the time, they are very important. I lack the historical experience to really understand why, though.
Just to add more context to the universal traits argument: I'm using them to implement internally opaque types. I'll dive into details in the next SIP meeting.
If we want to specialize "implicit class" to also be the only form of AnyVal-ness, then we should seriously consider adopting "extension methods" as a core part of the language, so that (opaque type aliases + extension methods) replace (implicit classes + value classes). That would really simplify Scala (as perceived if not in the core language spec).
I agree, extension methods seem to be way better in terms of perceived complexity. Never has there been a discussion about how extensions are overcomplicated in C# for example. Core language (i.e. compiler internals) may still reason about them as implicit classes, users don't have to know about the nitty gritty details under the hood.
@olafurpg Do you have any data on how widely are universal traits used based on corpus for scalafix?
@densh Here's what I could find in the community build https://gist.github.com/olafurpg/96a4de889475d91efa7a3508f9c3be19 The corpus consists of ~3 million LOC
@olafurpg FTR all the Scala.js results are spurious: they are either in overrides for the Scala lib (so the universal trait is really coming from the Scala lib, not from Scala.js) or in tests specifically written for universal traits ;)
So in practice there is 0 universal trait usage in Scala.js.
https://github.com/scala/scala-dev/issues/504 covers the Scala 2 part of this
https://contributors.scala-lang.org/t/pre-sip-unboxed-wrapper-types/987/104 has a lot of discussion
fresh discussions are happening as part of the Scala 3 SIP process
Most helpful comment
If we want to specialize "implicit class" to also be the only form of
AnyVal-ness, then we should seriously consider adopting "extension methods" as a core part of the language, so that (opaque type aliases + extension methods) replace (implicit classes + value classes). That would really simplify Scala (as perceived if not in the core language spec).Note that
AnyVals can extend universal traits. Opaque type aliases cannot. Cf.ArrayOpsfor a particularly core example. I would personally be happy with dropping that capability from the language, but @odersky mentioned that universal traits came from very serious considerations and that, at least at the time, they are very important. I lack the historical experience to really understand why, though.