@@ -232,13 +232,14 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
232
232
def compareNamed (tp1 : Type , tp2 : NamedType ): Boolean = {
233
233
implicit val ctx : Context = this .ctx
234
234
tp2.info match {
235
- case info2 : TypeAlias => recur(tp1, info2.alias)
235
+ case info2 : TypeAlias =>
236
+ recur(tp1, info2.alias) || tryPackagePrefix2(tp1, tp2)
236
237
case _ => tp1 match {
237
238
case tp1 : NamedType =>
238
239
tp1.info match {
239
240
case info1 : TypeAlias =>
240
241
if (recur(info1.alias, tp2)) return true
241
- if (tp1.prefix.isStable) return false
242
+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
242
243
// If tp1.prefix is stable, the alias does contain all information about the original ref, so
243
244
// there's no need to try something else. (This is important for performance).
244
245
// To see why we cannot in general stop here, consider:
@@ -260,7 +261,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
260
261
if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
261
262
ctx.erasedTypes ||
262
263
sym1.isStaticOwner ||
263
- isSubType(tp1.prefix, tp2.prefix) ||
264
+ isSubType(stripPackageObject( tp1.prefix), stripPackageObject( tp2.prefix) ) ||
264
265
thirdTryNamed(tp2)
265
266
else
266
267
( (tp1.name eq tp2.name)
@@ -359,7 +360,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
359
360
tp1.info match {
360
361
case info1 : TypeAlias =>
361
362
if (recur(info1.alias, tp2)) return true
362
- if (tp1.prefix.isStable) return false
363
+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
363
364
case _ =>
364
365
if (tp1 eq NothingType ) return true
365
366
}
@@ -1074,6 +1075,33 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
1074
1075
}
1075
1076
}
1076
1077
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`
1098
+ */
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))
1103
+ }
1104
+
1077
1105
/** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
1078
1106
def natValue (tp : Type ): Option [Int ] = constValue(tp) match {
1079
1107
case Some (Constant (n : Int )) if n >= 0 => Some (n)
0 commit comments