@@ -261,13 +261,13 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
261
261
if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
262
262
ctx.erasedTypes ||
263
263
sym1.isStaticOwner ||
264
- isSubType (tp1.prefix, tp2.prefix) ||
264
+ isSubPrefix (tp1.prefix, tp2.prefix) ||
265
265
thirdTryNamed(tp2)
266
266
else
267
267
( (tp1.name eq tp2.name)
268
268
&& tp1.isMemberRef
269
269
&& tp2.isMemberRef
270
- && isSubType (tp1.prefix, tp2.prefix)
270
+ && isSubPrefix (tp1.prefix, tp2.prefix)
271
271
&& tp1.signature == tp2.signature
272
272
&& ! (sym1.isClass && sym2.isClass) // class types don't subtype each other
273
273
) ||
@@ -296,12 +296,6 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
296
296
def compareThis = {
297
297
val cls2 = tp2.cls
298
298
tp1 match {
299
- case tp1 : ThisType =>
300
- // We treat two prefixes A.this, B.this as equivalent if
301
- // A's selftype derives from B and B's selftype derives from A.
302
- val cls1 = tp1.cls
303
- cls1.classInfo.selfType.derivesFrom(cls2) &&
304
- cls2.classInfo.selfType.derivesFrom(cls1)
305
299
case tp1 : NamedType if cls2.is(Module ) && cls2.eq(tp1.widen.typeSymbol) =>
306
300
cls2.isStaticOwner ||
307
301
recur(tp1.prefix, cls2.owner.thisType) ||
@@ -819,6 +813,44 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
819
813
false
820
814
}
821
815
816
+ /** When called from `pre1.A <:< pre2.A` does `pre1` relate to `pre2` so that
817
+ * the subtype test is true? This is the case if `pre1 <:< pre2`, or
818
+ * `pre1` and `pre2` are both this-types of related classes. Here, two classes
819
+ * are related if each of them has a self type that derives from the other.
820
+ *
821
+ * This criterion is a bit dubious. I.e. in the test
822
+ *
823
+ * A.this.T <:< B.this.T
824
+ *
825
+ * where `T` is the same type, what relationship must exist between A and B
826
+ * for the test to be guaranteed true? The problem is we can't tell without additional
827
+ * info. One could be an outer this at the point where we do the test, but that
828
+ * location is unknown to us.
829
+ *
830
+ * The conservative choice would be to require A == B, but then some tests involving
831
+ * self types fail. Specifically, t360, t361 and pat_iuli fail the pickling test, and
832
+ * Namer fails to compile. At line 203, we get
833
+ *
834
+ * val Deriver : Property.Key[typer.Deriver] = new Property.Key
835
+ * ^
836
+ * value Deriver in class Namer is not a legal implementation of `Deriver` in class Namer.
837
+ * its type dotty.tools.dotc.util.Property.Key[Namer.this.Deriver]
838
+ |* does not conform to dotty.tools.dotc.util.Property.Key[Typer.this.Deriver & Namer.this.Deriver]
839
+ */
840
+ def isSubPrefix (pre1 : Type , pre2 : Type ): Boolean =
841
+ pre1 match
842
+ case pre1 : ThisType =>
843
+ pre2 match
844
+ case pre2 : ThisType =>
845
+ if pre1.cls.classInfo.selfType.derivesFrom(pre2.cls)
846
+ && pre2.cls.classInfo.selfType.derivesFrom(pre1.cls)
847
+ then
848
+ subtyping.println(i " assume equal prefixes $pre1 $pre2" )
849
+ return true
850
+ case _ =>
851
+ case _ =>
852
+ isSubType(pre1, pre2)
853
+
822
854
/** Subtype test for the hk application `tp2 = tycon2[args2]`.
823
855
*/
824
856
def compareAppliedType2 (tp2 : AppliedType , tycon2 : Type , args2 : List [Type ]): Boolean = {
@@ -857,7 +889,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
857
889
858
890
val res = (
859
891
tycon1sym == tycon2sym
860
- && isSubType (tycon1.prefix, tycon2.prefix)
892
+ && isSubPrefix (tycon1.prefix, tycon2.prefix)
861
893
|| byGadtBounds(tycon1sym, tycon2, fromAbove = true )
862
894
|| byGadtBounds(tycon2sym, tycon1, fromAbove = false )
863
895
) && {
0 commit comments