diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 9dda18c72f26..465978d329e6 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -283,17 +283,28 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling val ctx = comparerContext given Context = ctx // optimization for performance val info2 = tp2.info + + /** Does `tp2` have a stable prefix? + * If that's not the case, following an alias via asSeenFrom could be lossy + * so we should not conclude `false` if comparing aliases fails. + * See pos/i17064.scala for a test case + */ + def hasStablePrefix(tp: NamedType) = + tp.prefix.isStable + info2 match case info2: TypeAlias => if recur(tp1, info2.alias) then return true - if tp2.asInstanceOf[TypeRef].canDropAlias then return false + if tp2.asInstanceOf[TypeRef].canDropAlias && hasStablePrefix(tp2) then + return false case _ => tp1 match case tp1: NamedType => tp1.info match { case info1: TypeAlias => if recur(info1.alias, tp2) then return true - if tp1.asInstanceOf[TypeRef].canDropAlias then return false + if tp1.asInstanceOf[TypeRef].canDropAlias && hasStablePrefix(tp2) then + return false case _ => } val sym2 = tp2.symbol @@ -302,7 +313,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling // For convenience we want X$ <:< X.type // This is safe because X$ self-type is X.type sym1 = sym1.companionModule - if ((sym1 ne NoSymbol) && (sym1 eq sym2)) + if (sym1 ne NoSymbol) && (sym1 eq sym2) then ctx.erasedTypes || sym1.isStaticOwner || isSubPrefix(tp1.prefix, tp2.prefix) || diff --git a/tests/neg/i15525.scala b/tests/neg/i15525.scala index b14c244b43c8..0813d7c82435 100644 --- a/tests/neg/i15525.scala +++ b/tests/neg/i15525.scala @@ -37,7 +37,7 @@ def element22( transmittable20.Type / transmittable21.Type } = ??? -def test22 = // error +def test22 = Resolution( element22( Resolution(element0), Resolution(element0), // error // error diff --git a/tests/pos/i17064.scala b/tests/pos/i17064.scala new file mode 100644 index 000000000000..e5a1f636f56c --- /dev/null +++ b/tests/pos/i17064.scala @@ -0,0 +1,10 @@ +class HiddenInner[+O<:Outer](val outer:O){ +} + +class Outer{ + type Inner = HiddenInner[this.type] +} + +val o : Outer = new Outer +def a : o.Inner = new o.Inner(o) +val b : Outer#Inner = a // DOES NOT COMPILE \ No newline at end of file