Skip to content

Unexpected erasure of opaque type with parameter #6159

Closed
@panacekcz

Description

@panacekcz

Outside its companion, opaque type defined using its type parameter erases to the bound of the parameter, not the actual type argument.
That is different from normal type alias and can lead to boxing of values or overloading errors.

Code:

trait A
trait B extends A

object O{
  opaque type T[X <: A] = X
  type U[X <: A] = X
  object T{
    def t(a: T[B]): T[B] = a
    def u(a: U[B]): U[B] = a
  }
  def t(a: T[B]): T[B] = a
  def u(a: U[B]): U[B] = a
}

With -Xprint:erasure:

... class T$ ... { ...
      def t(a: B): B = a
      def u(a: B): B = a
    }
    def t(a: A): A = a
    def u(a: B): B = a ...

Boxing

object O{
  opaque type T[X] = X
  object T{
    def wrap(a: Int): T[Int] = a
    def unwrap(a: T[Int]): Int = a
  }
  def w(a: Int): T[Int] = T.wrap(a)
  def u(a: T[Int]): Int = T.unwrap(a)
}

With -Xprint:erasure:

... def w(a: Int): Object = scala.Int.box(O.T.wrap(a))
    def u(a: Object): Int = O.T.unwrap(scala.Int.unbox(a)) ...

Overloading

object O{
  opaque type T[X] = X

  def m(a: T[Int]) = 1
  def m(a: T[String]) = 2
}

Output:

-- [E120] Duplicate Symbol Error: opaque-overload.scala:6:6 --------
6 |  def m(a: T[String]) = 2
  |      ^
  |      Double definition:
  |      def m(a: O.T.T[Int]): Int in object O at line 5 and
  |      def m(a: O.T.T[String]): Int in object O at line 6
  |      have the same type after erasure.
one error found

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions