@@ -226,13 +226,13 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
226
226
implicit val ctx : Context = this .ctx
227
227
tp2.info match {
228
228
case info2 : TypeAlias =>
229
- recur(tp1, info2.alias) || tryPackagePrefix2(tp1, tp2)
229
+ recur(tp1, info2.alias)
230
230
case _ => tp1 match {
231
231
case tp1 : NamedType =>
232
232
tp1.info match {
233
233
case info1 : TypeAlias =>
234
234
if (recur(info1.alias, tp2)) return true
235
- if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
235
+ if (tp1.prefix.isStable) return false
236
236
// If tp1.prefix is stable, the alias does contain all information about the original ref, so
237
237
// there's no need to try something else. (This is important for performance).
238
238
// To see why we cannot in general stop here, consider:
@@ -254,7 +254,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
254
254
if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
255
255
ctx.erasedTypes ||
256
256
sym1.isStaticOwner ||
257
- isSubType(stripPackageObject( tp1.prefix), stripPackageObject( tp2.prefix) ) ||
257
+ isSubType(tp1.prefix, tp2.prefix) ||
258
258
thirdTryNamed(tp2)
259
259
else
260
260
( (tp1.name eq tp2.name)
@@ -353,7 +353,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
353
353
tp1.info match {
354
354
case info1 : TypeAlias =>
355
355
if (recur(info1.alias, tp2)) return true
356
- if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
356
+ if (tp1.prefix.isStable) return tryLiftedToThis1
357
357
case _ =>
358
358
if (tp1 eq NothingType ) return true
359
359
}
@@ -456,7 +456,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
456
456
narrowGADTBounds(tp2, tp1, approx, isUpper = false )) &&
457
457
{ tp1.isRef(NothingClass ) || GADTusage (tp2.symbol) }
458
458
}
459
- isSubApproxHi(tp1, info2.lo) || compareGADT || fourthTry
459
+ isSubApproxHi(tp1, info2.lo) || compareGADT || tryLiftedToThis2 || fourthTry
460
460
461
461
case _ =>
462
462
val cls2 = tp2.symbol
@@ -715,7 +715,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
715
715
narrowGADTBounds(tp1, tp2, approx, isUpper = true )) &&
716
716
{ tp2.isRef(AnyClass ) || GADTusage (tp1.symbol) }
717
717
}
718
- isSubType(hi1, tp2, approx.addLow) || compareGADT
718
+ isSubType(hi1, tp2, approx.addLow) || compareGADT || tryLiftedToThis1
719
719
case _ =>
720
720
def isNullable (tp : Type ): Boolean = tp.widenDealias match {
721
721
case tp : TypeRef => tp.symbol.isNullableClass
@@ -959,7 +959,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
959
959
case _ =>
960
960
fourthTry
961
961
}
962
- }
962
+ } || tryLiftedToThis2
963
+
963
964
case _ : TypeVar =>
964
965
recur(tp1, tp2.superType)
965
966
case tycon2 : AnnotatedType if ! tycon2.isRefining =>
@@ -986,9 +987,11 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
986
987
isSubType(bounds(param1).hi.applyIfParameterized(args1), tp2, approx.addLow)
987
988
case tycon1 : TypeRef =>
988
989
val sym = tycon1.symbol
989
- ! sym.isClass && (
990
+ ! sym.isClass && {
990
991
defn.isCompiletime_S(sym) && compareS(tp1, tp2, fromBelow = false ) ||
991
- recur(tp1.superType, tp2))
992
+ recur(tp1.superType, tp2) ||
993
+ tryLiftedToThis1
994
+ }
992
995
case tycon1 : TypeProxy =>
993
996
recur(tp1.superType, tp2)
994
997
case _ =>
@@ -1029,6 +1032,16 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
1029
1032
def isSubApproxHi (tp1 : Type , tp2 : Type ): Boolean =
1030
1033
tp1.eq(tp2) || tp2.ne(NothingType ) && isSubType(tp1, tp2, approx.addHigh)
1031
1034
1035
+ def tryLiftedToThis1 : Boolean = {
1036
+ val tp1a = liftToThis(tp1)
1037
+ (tp1a ne tp1) && recur(tp1a, tp2)
1038
+ }
1039
+
1040
+ def tryLiftedToThis2 : Boolean = {
1041
+ val tp2a = liftToThis(tp2)
1042
+ (tp2a ne tp2) && recur(tp1, tp2a)
1043
+ }
1044
+
1032
1045
// begin recur
1033
1046
if (tp2 eq NoType ) false
1034
1047
else if (tp1 eq tp2) true
@@ -1058,31 +1071,39 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
1058
1071
}
1059
1072
}
1060
1073
1061
- /** If `tp` is a reference to a package object, a reference to the package itself,
1062
- * otherwise `tp`.
1063
- */
1064
- private def stripPackageObject (tp : Type ) = tp match {
1065
- case tp : TermRef if tp.symbol.isPackageObject => tp.symbol.owner.thisType
1066
- case tp : ThisType if tp.cls.isPackageObject => tp.cls.owner.thisType
1067
- case _ => tp
1068
- }
1069
-
1070
- /** If prefix of `tp1` is a reference to a package object, retry with
1071
- * the prefix pointing to the package itself, otherwise `false`
1072
- */
1073
- private def tryPackagePrefix1 (tp1 : NamedType , tp2 : Type ) = {
1074
- val pre1 = tp1.prefix
1075
- val pre1a = stripPackageObject(pre1)
1076
- (pre1a ne pre1) && isSubType(tp1.withPrefix(pre1a), tp2)
1077
- }
1078
-
1079
- /** If prefix of `tp2` is a reference to a package object, retry with
1080
- * the prefix pointing to the package itself, otherwise `false`
1074
+ /** If `tp` is an external reference to an enclosing module M that contains opaque types,
1075
+ * convert to M.this.
1076
+ * Note: It would be legal to do the lifting also if M does not contain opaque types,
1077
+ * but in this case the retries in tryLiftedToThis would be redundant.
1081
1078
*/
1082
- private def tryPackagePrefix2 (tp1 : Type , tp2 : NamedType ) = {
1083
- val pre2 = tp2.prefix
1084
- val pre2a = stripPackageObject(pre2)
1085
- (pre2a ne pre2) && isSubType(tp1, tp2.withPrefix(pre2a))
1079
+ private def liftToThis (tp : Type ): Type = {
1080
+
1081
+ def findEnclosingThis (moduleClass : Symbol , from : Symbol ): Type =
1082
+ if ((from.owner eq moduleClass) && from.isPackageObject && from.is(Opaque )) from.thisType
1083
+ else if (from.is(Package )) tp
1084
+ else if ((from eq moduleClass) && from.is(Opaque )) from.thisType
1085
+ else if (from eq NoSymbol ) tp
1086
+ else findEnclosingThis(moduleClass, from.owner)
1087
+
1088
+ tp.stripTypeVar.stripAnnots match {
1089
+ case tp : TermRef if tp.symbol.is(Module ) =>
1090
+ findEnclosingThis(tp.symbol.moduleClass, ctx.owner)
1091
+ case tp : TypeRef =>
1092
+ val pre1 = liftToThis(tp.prefix)
1093
+ if (pre1 ne tp.prefix) tp.withPrefix(pre1) else tp
1094
+ case tp : ThisType if tp.cls.is(Package ) =>
1095
+ findEnclosingThis(tp.cls, ctx.owner)
1096
+ case tp : AppliedType =>
1097
+ val tycon1 = liftToThis(tp.tycon)
1098
+ if (tycon1 ne tp.tycon) tp.derivedAppliedType(tycon1, tp.args) else tp
1099
+ case tp : TypeVar if tp.isInstantiated =>
1100
+ liftToThis(tp.inst)
1101
+ case tp : AnnotatedType =>
1102
+ val parent1 = liftToThis(tp.parent)
1103
+ if (parent1 ne tp.parent) tp.derivedAnnotatedType(parent1, tp.annot) else tp
1104
+ case _ =>
1105
+ tp
1106
+ }
1086
1107
}
1087
1108
1088
1109
/** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
0 commit comments