@@ -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 util .NoSourcePosition
13
14
import config .Config
@@ -182,16 +183,37 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
182
183
try op finally comparedTypeLambdas = saved
183
184
184
185
protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
186
+ inline def followAlias [T ](inline tp : Type )(inline default : T )(inline f : (TypeProxy , Symbol ) => T ): T =
187
+ tp.stripAnnots.stripTypeVar match
188
+ case tp : (AppliedType | TypeRef ) => f(tp, tp.typeSymbol)
189
+ case _ => default
190
+
191
+ @ tailrec def dealias (tp : Type , syms : Set [Symbol ]): Type =
192
+ followAlias(tp)(NoType ) { (tp, sym) =>
193
+ if syms contains sym then tp
194
+ else if sym.isAliasType then dealias(tp.superType, syms)
195
+ else NoType
196
+ }
197
+
198
+ @ tailrec def aliasedSymbols (tp : Type , result : Set [Symbol ] = Set .empty): Set [Symbol ] =
199
+ followAlias(tp)(result) { (tp, sym) =>
200
+ if sym.isAliasType then aliasedSymbols(tp.superType, result + sym)
201
+ else if sym.exists && (sym ne AnyClass ) then result + sym
202
+ else result
203
+ }
204
+
205
+ val tp1dealiased = dealias(tp1, aliasedSymbols(tp2)) orElse tp1
206
+
185
207
val savedApprox = approx
186
208
val savedLeftRoot = leftRoot
187
209
if (a == ApproxState .Fresh ) {
188
210
this .approx = ApproxState .None
189
- this .leftRoot = tp1
211
+ this .leftRoot = tp1dealiased
190
212
}
191
213
else this .approx = a
192
- try recur(tp1 , tp2)
214
+ try recur(tp1dealiased , tp2)
193
215
catch {
194
- case ex : Throwable => handleRecursive(" subtype" , i " $tp1 <:< $tp2" , ex, weight = 2 )
216
+ case ex : Throwable => handleRecursive(" subtype" , i " $tp1dealiased <:< $tp2" , ex, weight = 2 )
195
217
}
196
218
finally {
197
219
this .approx = savedApprox
@@ -1026,7 +1048,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1026
1048
def isMatchingApply (tp1 : Type ): Boolean = tp1.widen match {
1027
1049
case tp1 @ AppliedType (tycon1, args1) =>
1028
1050
// We intentionally do not automatically dealias `tycon1` or `tycon2` here.
1029
- // `TypeApplications#appliedTo ` already takes care of dealiasing type
1051
+ // `isSubType ` already takes care of dealiasing type
1030
1052
// constructors when this can be done without affecting type
1031
1053
// inference, doing it here would not only prevent code from compiling
1032
1054
// but could also result in the wrong thing being inferred later, for example
0 commit comments