@@ -8,6 +8,7 @@ import Phases.{gettersPhase, elimByNamePhase}
8
8
import StdNames .nme
9
9
import TypeOps .refineUsingParent
10
10
import collection .mutable
11
+ import annotation .tailrec
11
12
import util .Stats
12
13
import config .Config
13
14
import config .Feature .migrateTo3
@@ -178,16 +179,37 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
178
179
try op finally comparedTypeLambdas = saved
179
180
180
181
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
+
181
203
val savedApprox = approx
182
204
val savedLeftRoot = leftRoot
183
205
if (a == ApproxState .Fresh ) {
184
206
this .approx = ApproxState .None
185
- this .leftRoot = tp1
207
+ this .leftRoot = tp1dealiased
186
208
}
187
209
else this .approx = a
188
- try recur(tp1 , tp2)
210
+ try recur(tp1dealiased , tp2)
189
211
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 )
191
213
}
192
214
finally {
193
215
this .approx = savedApprox
@@ -1009,7 +1031,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1009
1031
def isMatchingApply (tp1 : Type ): Boolean = tp1.widen match {
1010
1032
case tp1 @ AppliedType (tycon1, args1) =>
1011
1033
// 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
1013
1035
// constructors when this can be done without affecting type
1014
1036
// inference, doing it here would not only prevent code from compiling
1015
1037
// but could also result in the wrong thing being inferred later, for example
0 commit comments