Proposal for Opaque Type Aliases

Is it possible to avoid the new keyword opaque, in favor of reusing existing self-type syntax?

Can we allow type ID = Any { this: Long => } instead of opaque type ID = Long?

The self-type syntax has an additional advantage: it allows parts of the supertypes or members to be transparent.

type ID = Any { this: Long => }

implicitly[ID <:< AnyVal] // should not compile

type ID2 = AnyVal {
  // The actual self-type is `AnyVal { def +(rhs: Long): Long } with Long`,
  // which can be proven to be same type of `Long`, when calculating its `glb`
  this: Long => 

  def +(rhs: Long): Long
}

implicitly[ID2 <:< AnyVal] // should compile 

def minus1(id2: ID2): Long = {
  id2 - 1L // should not compile.
}

def plus1(id2: ID2): Long = {
  id2 + 1L // should compile and should not be a reflective call, because the backend knows `ID2 =:= Long`
}

We can also allow casting a trait or a class to its self-type in its companion object for consistency.

2 Likes