diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 878220cd85d5..ad0f07a5ac50 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1888,7 +1888,15 @@ object Types { case st => st } - /** Same as superType, except that opaque types are treated as transparent aliases */ + /** Same as superType, except for two differences: + * - opaque types are treated as transparent aliases + * - applied type are matchtype-reduced if possible + * + * Note: the reason to reduce match type aliases here and not in `superType` + * is that `superType` is context-independent and cached, whereas matchtype + * reduction depends on context and should not be cached (at least not without + * the very specific cache invalidation condition for matchtypes). + */ def translucentSuperType(using Context): Type = superType } @@ -4011,7 +4019,7 @@ object Types { case tycon: TypeRef if tycon.symbol.isOpaqueAlias => tycon.translucentSuperType.applyIfParameterized(args) case _ => - superType + tryNormalize.orElse(superType) } inline def map(inline op: Type => Type)(using Context) = diff --git a/tests/pos/i7894.scala b/tests/pos/i7894.scala new file mode 100644 index 000000000000..74cd3e3cb247 --- /dev/null +++ b/tests/pos/i7894.scala @@ -0,0 +1,16 @@ +case class Box[T](t: T) + +type Boxed[T <: Tuple] <: Tuple = T match { + case EmptyTuple => EmptyTuple + case h *: t => Box[h] *: Boxed[t] +} + +trait Cmp[T <: Tuple] { def cmp(t: T, b: Boxed[T]): Boolean } + +object UnitCmp extends Cmp[EmptyTuple] { + def cmp(t: EmptyTuple, b: EmptyTuple): Boolean = true +} + +object UnitCmp2 extends Cmp[EmptyTuple] { + def cmp(t: EmptyTuple, b: Boxed[EmptyTuple]): Boolean = true +} diff --git a/tests/pos/i8666.scala b/tests/pos/i8666.scala new file mode 100644 index 000000000000..307a4617b172 --- /dev/null +++ b/tests/pos/i8666.scala @@ -0,0 +1,10 @@ +class Foo[A, B]() + +type FooSnd[X] = X match + case Foo[_, b] => b + +trait Bar[A]: + def bar(h: FooSnd[A]): Int + +val foo: Bar[Foo[String, Int]] = new Bar[Foo[String, Int]]: + def bar(h: FooSnd[Foo[String, Int]]) = h