@@ -262,13 +262,13 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
262262 if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
263263 ctx.erasedTypes ||
264264 sym1.isStaticOwner ||
265- isSubType (tp1.prefix, tp2.prefix) ||
265+ isSubPrefix (tp1.prefix, tp2.prefix) ||
266266 thirdTryNamed(tp2)
267267 else
268268 ( (tp1.name eq tp2.name)
269269 && tp1.isMemberRef
270270 && tp2.isMemberRef
271- && isSubType (tp1.prefix, tp2.prefix)
271+ && isSubPrefix (tp1.prefix, tp2.prefix)
272272 && tp1.signature == tp2.signature
273273 && ! (sym1.isClass && sym2.isClass) // class types don't subtype each other
274274 ) ||
@@ -297,12 +297,6 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
297297 def compareThis = {
298298 val cls2 = tp2.cls
299299 tp1 match {
300- case tp1 : ThisType =>
301- // We treat two prefixes A.this, B.this as equivalent if
302- // A's selftype derives from B and B's selftype derives from A.
303- val cls1 = tp1.cls
304- cls1.classInfo.selfType.derivesFrom(cls2) &&
305- cls2.classInfo.selfType.derivesFrom(cls1)
306300 case tp1 : NamedType if cls2.is(Module ) && cls2.eq(tp1.widen.typeSymbol) =>
307301 cls2.isStaticOwner ||
308302 recur(tp1.prefix, cls2.owner.thisType) ||
@@ -498,7 +492,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
498492 if (base.typeSymbol == cls2) return true
499493 }
500494 else if tp1.isLambdaSub && ! tp1.isAnyKind then
501- return recur(tp1, EtaExpansion (cls2.typeRef ))
495+ return recur(tp1, EtaExpansion (tp2 ))
502496 fourthTry
503497 }
504498
@@ -820,6 +814,44 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
820814 false
821815 }
822816
817+ /** When called from `pre1.A <:< pre2.A` does `pre1` relate to `pre2` so that
818+ * the subtype test is true? This is the case if `pre1 <:< pre2`, or
819+ * `pre1` and `pre2` are both this-types of related classes. Here, two classes
820+ * are related if each of them has a self type that derives from the other.
821+ *
822+ * This criterion is a bit dubious. I.e. in the test
823+ *
824+ * A.this.T <:< B.this.T
825+ *
826+ * where `T` is the same type, what relationship must exist between A and B
827+ * for the test to be guaranteed true? The problem is we can't tell without additional
828+ * info. One could be an outer this at the point where we do the test, but that
829+ * location is unknown to us.
830+ *
831+ * The conservative choice would be to require A == B, but then some tests involving
832+ * self types fail. Specifically, t360, t361 and pat_iuli fail the pickling test, and
833+ * Namer fails to compile. At line 203, we get
834+ *
835+ * val Deriver : Property.Key[typer.Deriver] = new Property.Key
836+ * ^
837+ * value Deriver in class Namer is not a legal implementation of `Deriver` in class Namer.
838+ * its type dotty.tools.dotc.util.Property.Key[Namer.this.Deriver]
839+ |* does not conform to dotty.tools.dotc.util.Property.Key[Typer.this.Deriver & Namer.this.Deriver]
840+ */
841+ def isSubPrefix (pre1 : Type , pre2 : Type ): Boolean =
842+ pre1 match
843+ case pre1 : ThisType =>
844+ pre2 match
845+ case pre2 : ThisType =>
846+ if pre1.cls.classInfo.selfType.derivesFrom(pre2.cls)
847+ && pre2.cls.classInfo.selfType.derivesFrom(pre1.cls)
848+ then
849+ subtyping.println(i " assume equal prefixes $pre1 $pre2" )
850+ return true
851+ case _ =>
852+ case _ =>
853+ isSubType(pre1, pre2)
854+
823855 /** Subtype test for the hk application `tp2 = tycon2[args2]`.
824856 */
825857 def compareAppliedType2 (tp2 : AppliedType , tycon2 : Type , args2 : List [Type ]): Boolean = {
@@ -858,7 +890,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
858890
859891 val res = (
860892 tycon1sym == tycon2sym
861- && isSubType (tycon1.prefix, tycon2.prefix)
893+ && isSubPrefix (tycon1.prefix, tycon2.prefix)
862894 || byGadtBounds(tycon1sym, tycon2, fromAbove = true )
863895 || byGadtBounds(tycon2sym, tycon1, fromAbove = false )
864896 ) && {
0 commit comments