Skip to content

Commit acae5ed

Browse files
committed
Correctly handle opaque types with type parameters
1 parent 3f6bdae commit acae5ed

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

src/reflect/scala/reflect/internal/transform/Erasure.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,15 @@ trait Erasure {
150150
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref)
151151
else if (isDottyEnumSingleton(sym)) apply(mergeParents(tp.parents)) // TODO [tasty]: dotty enum singletons are not modules.
152152
else if (sym.isClass) eraseNormalClassRef(tref)
153-
else apply(transparentDealias(sym, pre, sym.owner)) // alias type or abstract type (including opaque type)
153+
else {
154+
// This `else` branch is triggered when we're erasing a type alias or abstract type
155+
// (including Scala 3 opaque types). Dealias and erase the underlying type. For polymorphic aliases like
156+
// `type F[X] = X`, we must apply the type arguments to get the concrete type before erasure.
157+
val dealiased = transparentDealias(sym, pre, sym.owner)
158+
val applied = if (args.nonEmpty) appliedType(dealiased, args) else dealiased
159+
160+
apply(applied)
161+
}
154162
case PolyType(tparams, restpe) =>
155163
apply(restpe)
156164
case ExistentialType(tparams, restpe) =>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package tastytest
2+
3+
object TestOpaqueConstructorParameter extends Suite("TestOpaqueConstructorParameter") {
4+
import OpaqueConstructorParameter._
5+
6+
test("constructor with opaque type parameters") {
7+
val holder = new OpaqueHolder(id(42L), id("hello"))
8+
9+
assert(holder.longId == 42L)
10+
assert(holder.stringId == "hello")
11+
}
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package tastytest
2+
3+
object OpaqueConstructorParameter {
4+
opaque type Id[X] <: X = X
5+
6+
def id[X](x: X): Id[X] = x
7+
}
8+
9+
class OpaqueHolder(val longId: OpaqueConstructorParameter.Id[Long], val stringId: OpaqueConstructorParameter.Id[String])

0 commit comments

Comments
 (0)