@@ -225,13 +225,14 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
225
225
def compareNamed (tp1 : Type , tp2 : NamedType ): Boolean = {
226
226
implicit val ctx : Context = this .ctx
227
227
tp2.info match {
228
- case info2 : TypeAlias => recur(tp1, info2.alias)
228
+ case info2 : TypeAlias =>
229
+ recur(tp1, info2.alias) || tryPackagePrefix2(tp1, tp2)
229
230
case _ => tp1 match {
230
231
case tp1 : NamedType =>
231
232
tp1.info match {
232
233
case info1 : TypeAlias =>
233
234
if (recur(info1.alias, tp2)) return true
234
- if (tp1.prefix.isStable) return false
235
+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
235
236
// If tp1.prefix is stable, the alias does contain all information about the original ref, so
236
237
// there's no need to try something else. (This is important for performance).
237
238
// To see why we cannot in general stop here, consider:
@@ -253,7 +254,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
253
254
if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
254
255
ctx.erasedTypes ||
255
256
sym1.isStaticOwner ||
256
- isSubType(tp1.prefix, tp2.prefix) ||
257
+ isSubType(stripPackageObject( tp1.prefix), stripPackageObject( tp2.prefix) ) ||
257
258
thirdTryNamed(tp2)
258
259
else
259
260
( (tp1.name eq tp2.name)
@@ -352,7 +353,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
352
353
tp1.info match {
353
354
case info1 : TypeAlias =>
354
355
if (recur(info1.alias, tp2)) return true
355
- if (tp1.prefix.isStable) return false
356
+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
356
357
case _ =>
357
358
if (tp1 eq NothingType ) return true
358
359
}
@@ -1057,6 +1058,33 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
1057
1058
}
1058
1059
}
1059
1060
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`
1081
+ */
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))
1086
+ }
1087
+
1060
1088
/** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
1061
1089
def natValue (tp : Type ): Option [Int ] = constValue(tp) match {
1062
1090
case Some (Constant (n : Int )) if n >= 0 => Some (n)
0 commit comments