Proposal for Opaque Type Aliases

Again, it seems that opaques share similarities and differences with all of the other components (classes, type aliases and type members), but they are neither. They have their own unique semantics.

I believe that associating them with type would be confusing, as we can already see here the confusion between type aliases and type members, which are different but are mistaken as similar since they share the same keyword. Let’s not add yet another meaning into that soup.

As @kai shown, they could actually be achieved with Scala 2 (given that the performance is the same as what is proposed), so it’s only a matter of syntactic sugar. If that’s what this all about, I suggest making their syntax tailored specifically to their use case:

opaque Permission(i: Int) {
  def |(other: Permission): Permission = Permission(i | other)
  def isOneOf(permission: Permission): Boolean = (i & permission) != 0
}

object Permission {
  // provided by default and can be overridden with a different implementation
  def apply(i: Int): Permission = i
  // not provided by default
  def apply(name: String): Permission = ???

  val WriteOnly = Permission(2)
  val ReadOnly = Permission(4)
}

import Permission._

val readWrite = WriteOnly | ReadOnly // compiles
val readWrite: Int = WriteOnly | ReadOnly // doesn't compile

ReadOnly.isOneOf(readWrite) // compiles
ReadOnly.isOneOf(6) // doesn't compiles
ReadOnly.toDouble // doesn't compile

2 == WriteOnly // compiles and returns `true`
obj.isInstnaceOf[Permission] // doesn't compile
obj match { case p: Permission => ??? }  // doesn't compile