@@ -232,13 +232,14 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
232232 def compareNamed (tp1 : Type , tp2 : NamedType ): Boolean = {
233233 implicit val ctx : Context = this .ctx
234234 tp2.info match {
235- case info2 : TypeAlias => recur(tp1, info2.alias)
235+ case info2 : TypeAlias =>
236+ recur(tp1, info2.alias) || tryPackagePrefix2(tp1, tp2)
236237 case _ => tp1 match {
237238 case tp1 : NamedType =>
238239 tp1.info match {
239240 case info1 : TypeAlias =>
240241 if (recur(info1.alias, tp2)) return true
241- if (tp1.prefix.isStable) return false
242+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
242243 // If tp1.prefix is stable, the alias does contain all information about the original ref, so
243244 // there's no need to try something else. (This is important for performance).
244245 // To see why we cannot in general stop here, consider:
@@ -260,7 +261,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
260261 if ((sym1 ne NoSymbol ) && (sym1 eq sym2))
261262 ctx.erasedTypes ||
262263 sym1.isStaticOwner ||
263- isSubType(tp1.prefix, tp2.prefix) ||
264+ isSubType(stripPackageObject( tp1.prefix), stripPackageObject( tp2.prefix) ) ||
264265 thirdTryNamed(tp2)
265266 else
266267 ( (tp1.name eq tp2.name)
@@ -359,7 +360,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
359360 tp1.info match {
360361 case info1 : TypeAlias =>
361362 if (recur(info1.alias, tp2)) return true
362- if (tp1.prefix.isStable) return false
363+ if (tp1.prefix.isStable) return tryPackagePrefix1(tp1, tp2)
363364 case _ =>
364365 if (tp1 eq NothingType ) return true
365366 }
@@ -1074,6 +1075,33 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
10741075 }
10751076 }
10761077
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+
10771105 /** Optionally, the `n` such that `tp <:< ConstantType(Constant(n: Int))` */
10781106 def natValue (tp : Type ): Option [Int ] = constValue(tp) match {
10791107 case Some (Constant (n : Int )) if n >= 0 => Some (n)
0 commit comments