@@ -233,13 +233,13 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
233
233
implicit val ctx : Context = this .ctx
234
234
tp2.info match {
235
235
case info2 : TypeAlias =>
236
- recur(tp1, info2.alias) || tryPackagePrefix2(tp1, tp2)
236
+ recur(tp1, info2.alias)
237
237
case _ => tp1 match {
238
238
case tp1 : NamedType =>
239
239
tp1.info match {
240
240
case info1 : TypeAlias =>
241
241
if (recur(info1.alias, tp2)) return true
242
- if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
242
+ if (tp1.prefix.isStable) return false
243
243
// If tp1.prefix is stable, the alias does contain all information about the original ref, so
244
244
// there's no need to try something else. (This is important for performance).
245
245
// To see why we cannot in general stop here, consider:
@@ -261,7 +261,7 @@ 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(stripPackageObject( tp1.prefix), stripPackageObject( tp2.prefix) ) ||
264
+ isSubType(tp1.prefix, tp2.prefix) ||
265
265
thirdTryNamed(tp2)
266
266
else
267
267
( (tp1.name eq tp2.name)
@@ -360,7 +360,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
360
360
tp1.info match {
361
361
case info1 : TypeAlias =>
362
362
if (recur(info1.alias, tp2)) return true
363
- if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
363
+ if (tp1.prefix.isStable) return tryLiftedToThis1
364
364
case _ =>
365
365
if (tp1 eq NothingType ) return true
366
366
}
@@ -463,7 +463,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
463
463
narrowGADTBounds(tp2, tp1, approx, isUpper = false )) &&
464
464
{ tp1.isRef(NothingClass ) || GADTusage (tp2.symbol) }
465
465
}
466
- isSubApproxHi(tp1, info2.lo) || compareGADT || fourthTry
466
+ isSubApproxHi(tp1, info2.lo) || compareGADT || tryLiftedToThis2 || fourthTry
467
467
468
468
case _ =>
469
469
val cls2 = tp2.symbol
@@ -722,7 +722,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
722
722
narrowGADTBounds(tp1, tp2, approx, isUpper = true )) &&
723
723
{ tp2.isRef(AnyClass ) || GADTusage (tp1.symbol) }
724
724
}
725
- isSubType(hi1, tp2, approx.addLow) || compareGADT
725
+ isSubType(hi1, tp2, approx.addLow) || compareGADT || tryLiftedToThis1
726
726
case _ =>
727
727
def isNullable (tp : Type ): Boolean = tp.widenDealias match {
728
728
case tp : TypeRef => tp.symbol.isNullableClass
@@ -976,7 +976,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
976
976
case _ =>
977
977
fourthTry
978
978
}
979
- }
979
+ } || tryLiftedToThis2
980
+
980
981
case _ : TypeVar =>
981
982
recur(tp1, tp2.superType)
982
983
case tycon2 : AnnotatedType if ! tycon2.isRefining =>
@@ -1003,9 +1004,11 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
1003
1004
isSubType(bounds(param1).hi.applyIfParameterized(args1), tp2, approx.addLow)
1004
1005
case tycon1 : TypeRef =>
1005
1006
val sym = tycon1.symbol
1006
- ! sym.isClass && (
1007
+ ! sym.isClass && {
1007
1008
defn.isCompiletime_S(sym) && compareS(tp1, tp2, fromBelow = false ) ||
1008
- recur(tp1.superType, tp2))
1009
+ recur(tp1.superType, tp2) ||
1010
+ tryLiftedToThis1
1011
+ }
1009
1012
case tycon1 : TypeProxy =>
1010
1013
recur(tp1.superType, tp2)
1011
1014
case _ =>
@@ -1046,6 +1049,16 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
1046
1049
def isSubApproxHi (tp1 : Type , tp2 : Type ): Boolean =
1047
1050
tp1.eq(tp2) || tp2.ne(NothingType ) && isSubType(tp1, tp2, approx.addHigh)
1048
1051
1052
+ def tryLiftedToThis1 : Boolean = {
1053
+ val tp1a = liftToThis(tp1)
1054
+ (tp1a ne tp1) && recur(tp1a, tp2)
1055
+ }
1056
+
1057
+ def tryLiftedToThis2 : Boolean = {
1058
+ val tp2a = liftToThis(tp2)
1059
+ (tp2a ne tp2) && recur(tp1, tp2a)
1060
+ }
1061
+
1049
1062
// begin recur
1050
1063
if (tp2 eq NoType ) false
1051
1064
else if (tp1 eq tp2) true
@@ -1075,31 +1088,39 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
1075
1088
}
1076
1089
}
1077
1090
1078
- /** If `tp` is a reference to a package object, a reference to the package itself,
1079
- * otherwise `tp`.
1080
- */
1081
- private def stripPackageObject (tp : Type ) = tp match {
1082
- case tp : TermRef if tp.symbol.isPackageObject => tp.symbol.owner.thisType
1083
- case tp : ThisType if tp.cls.isPackageObject => tp.cls.owner.thisType
1084
- case _ => tp
1085
- }
1086
-
1087
- /** If prefix of `tp1` is a reference to a package object, retry with
1088
- * the prefix pointing to the package itself, otherwise `false`
1089
- */
1090
- private def tryPackagePrefix1 (tp1 : NamedType , tp2 : Type ) = {
1091
- val pre1 = tp1.prefix
1092
- val pre1a = stripPackageObject(pre1)
1093
- (pre1a ne pre1) && isSubType(tp1.withPrefix(pre1a), tp2)
1094
- }
1095
-
1096
- /** If prefix of `tp2` is a reference to a package object, retry with
1097
- * the prefix pointing to the package itself, otherwise `false`
1091
+ /** If `tp` is an external reference to an enclosing module M that contains opaque types,
1092
+ * convert to M.this.
1093
+ * Note: It would be legal to do the lifting also if M does not contain opaque types,
1094
+ * but in this case the retries in tryLiftedToThis would be redundant.
1098
1095
*/
1099
- private def tryPackagePrefix2 (tp1 : Type , tp2 : NamedType ) = {
1100
- val pre2 = tp2.prefix
1101
- val pre2a = stripPackageObject(pre2)
1102
- (pre2a ne pre2) && isSubType(tp1, tp2.withPrefix(pre2a))
1096
+ private def liftToThis (tp : Type ): Type = {
1097
+
1098
+ def findEnclosingThis (moduleClass : Symbol , from : Symbol ): Type =
1099
+ if ((from.owner eq moduleClass) && from.isPackageObject && from.is(Opaque )) from.thisType
1100
+ else if (from.is(Package )) tp
1101
+ else if ((from eq moduleClass) && from.is(Opaque )) from.thisType
1102
+ else if (from eq NoSymbol ) tp
1103
+ else findEnclosingThis(moduleClass, from.owner)
1104
+
1105
+ tp.stripTypeVar.stripAnnots match {
1106
+ case tp : TermRef if tp.symbol.is(Module ) =>
1107
+ findEnclosingThis(tp.symbol.moduleClass, ctx.owner)
1108
+ case tp : TypeRef =>
1109
+ val pre1 = liftToThis(tp.prefix)
1110
+ if (pre1 ne tp.prefix) tp.withPrefix(pre1) else tp
1111
+ case tp : ThisType if tp.cls.is(Package ) =>
1112
+ findEnclosingThis(tp.cls, ctx.owner)
1113
+ case tp : AppliedType =>
1114
+ val tycon1 = liftToThis(tp.tycon)
1115
+ if (tycon1 ne tp.tycon) tp.derivedAppliedType(tycon1, tp.args) else tp
1116
+ case tp : TypeVar if tp.isInstantiated =>
1117
+ liftToThis(tp.inst)
1118
+ case tp : AnnotatedType =>
1119
+ val parent1 = liftToThis(tp.parent)
1120
+ if (parent1 ne tp.parent) tp.derivedAnnotatedType(parent1, tp.annot) else tp
1121
+ case _ =>
1122
+ tp
1123
+ }
1103
1124
}
1104
1125
1105
1126
/** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
0 commit comments