@@ -8,6 +8,7 @@ import Phases.{gettersPhase, elimByNamePhase}
88import StdNames .nme
99import TypeOps .refineUsingParent
1010import collection .mutable
11+ import annotation .tailrec
1112import util .Stats
1213import config .Config
1314import config .Feature .migrateTo3
@@ -178,16 +179,37 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
178179 try op finally comparedTypeLambdas = saved
179180
180181 protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
182+ inline def followAlias [T ](inline tp : Type )(inline default : T )(inline f : (TypeProxy , Symbol ) => T ): T =
183+ tp.stripAnnots.stripTypeVar match
184+ case tp : (AppliedType | TypeRef ) => f(tp, tp.typeSymbol)
185+ case _ => default
186+
187+ @ tailrec def dealias (tp : Type , syms : Set [Symbol ]): Type =
188+ followAlias(tp)(NoType ) { (tp, sym) =>
189+ if syms contains sym then tp
190+ else if sym.isAliasType then dealias(tp.superType, syms)
191+ else NoType
192+ }
193+
194+ @ tailrec def aliasedSymbols (tp : Type , result : Set [Symbol ] = Set .empty): Set [Symbol ] =
195+ followAlias(tp)(Set .empty) { (tp, sym) =>
196+ if sym.isAliasType then aliasedSymbols(tp.superType, result + sym)
197+ else if sym.exists && (sym ne AnyClass ) then result + sym
198+ else Set .empty
199+ }
200+
201+ val tp1dealiased = dealias(tp1, aliasedSymbols(tp2)) orElse tp1
202+
181203 val savedApprox = approx
182204 val savedLeftRoot = leftRoot
183205 if (a == ApproxState .Fresh ) {
184206 this .approx = ApproxState .None
185- this .leftRoot = tp1
207+ this .leftRoot = tp1dealiased
186208 }
187209 else this .approx = a
188- try recur(tp1 , tp2)
210+ try recur(tp1dealiased , tp2)
189211 catch {
190- case ex : Throwable => handleRecursive(" subtype" , i " $tp1 <:< $tp2" , ex, weight = 2 )
212+ case ex : Throwable => handleRecursive(" subtype" , i " $tp1dealiased <:< $tp2" , ex, weight = 2 )
191213 }
192214 finally {
193215 this .approx = savedApprox
@@ -1009,7 +1031,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10091031 def isMatchingApply (tp1 : Type ): Boolean = tp1.widen match {
10101032 case tp1 @ AppliedType (tycon1, args1) =>
10111033 // We intentionally do not automatically dealias `tycon1` or `tycon2` here.
1012- // `TypeApplications#appliedTo ` already takes care of dealiasing type
1034+ // `isSubType ` already takes care of dealiasing type
10131035 // constructors when this can be done without affecting type
10141036 // inference, doing it here would not only prevent code from compiling
10151037 // but could also result in the wrong thing being inferred later, for example
0 commit comments