Skip to content

Commit a4b11d1

Browse files
committed
performance improvements for less eager dealiasing
1 parent 569e4b9 commit a4b11d1

File tree

1 file changed

+36
-30
lines changed

1 file changed

+36
-30
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,37 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
133133
}
134134

135135
def necessarySubType(tp1: Type, tp2: Type): Boolean =
136+
inline def followAlias[T](inline tp: Type)(inline default: T)(inline f: (TypeProxy, Symbol) => T): T =
137+
tp match
138+
case tp: (AppliedType | TypeRef) => f(tp, tp.typeSymbol)
139+
case _ => default
140+
141+
@tailrec def aliasedSymbols(tp: Type, result: Set[Symbol] = Set.empty): Set[Symbol] =
142+
followAlias(tp)(result) { (tp, sym) =>
143+
if sym.isAliasType then aliasedSymbols(tp.superType, result + sym)
144+
else if sym.exists && (sym ne AnyClass) then result + sym
145+
else result
146+
}
147+
148+
@tailrec def dealias(tp: Type, syms: Set[Symbol]): Type =
149+
followAlias(tp)(NoType) { (tp, sym) =>
150+
if syms contains sym then tp
151+
else if sym.isAliasType then dealias(tp.superType, syms)
152+
else NoType
153+
}
154+
136155
val saved = myNecessaryConstraintsOnly
137156
myNecessaryConstraintsOnly = true
138-
try topLevelSubType(tp1, tp2)
139-
finally myNecessaryConstraintsOnly = saved
157+
158+
try
159+
val tryDealias = (tp2 ne tp1) && (tp2 ne WildcardType) && followAlias(tp1)(false) { (_, sym) => sym.isAliasType }
160+
if tryDealias then
161+
topLevelSubType(dealias(tp1, aliasedSymbols(tp2)) orElse tp1, tp2)
162+
else
163+
topLevelSubType(tp1, tp2)
164+
finally
165+
myNecessaryConstraintsOnly = saved
166+
end necessarySubType
140167

141168
def testSubType(tp1: Type, tp2: Type): CompareResult =
142169
GADTused = false
@@ -183,37 +210,16 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
183210
try op finally comparedTypeLambdas = saved
184211

185212
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-
207213
val savedApprox = approx
208214
val savedLeftRoot = leftRoot
209215
if (a == ApproxState.Fresh) {
210216
this.approx = ApproxState.None
211-
this.leftRoot = tp1dealiased
217+
this.leftRoot = tp1
212218
}
213219
else this.approx = a
214-
try recur(tp1dealiased, tp2)
220+
try recur(tp1, tp2)
215221
catch {
216-
case ex: Throwable => handleRecursive("subtype", i"$tp1dealiased <:< $tp2", ex, weight = 2)
222+
case ex: Throwable => handleRecursive("subtype", i"$tp1 <:< $tp2", ex, weight = 2)
217223
}
218224
finally {
219225
this.approx = savedApprox
@@ -411,14 +417,14 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
411417
case tp2: TypeParamRef =>
412418
constraint.entry(tp2) match {
413419
case TypeBounds(lo, hi) =>
414-
val aliasLo = tp1 != lo && info1.alias == lo
415-
val aliasHi = tp1 != hi && info1.alias == hi
420+
val aliasLo = (tp1 ne lo) && (info1.alias eq lo)
421+
val aliasHi = (tp1 ne hi) && (info1.alias eq hi)
416422
if aliasLo || aliasHi then
417423
constraint = constraint.updateEntry(tp2, TypeBounds(
418424
if aliasLo then tp1 else lo,
419425
if aliasHi then tp1 else hi))
420426
case tp =>
421-
if tp1 != tp && info1.alias == tp then
427+
if (tp1 ne tp) && (info1.alias eq tp) then
422428
constraint = constraint.updateEntry(tp2, tp1)
423429
}
424430
case _ =>
@@ -1066,7 +1072,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
10661072
def isMatchingApply(tp1: Type): Boolean = tp1.widen match {
10671073
case tp1 @ AppliedType(tycon1, args1) =>
10681074
// We intentionally do not automatically dealias `tycon1` or `tycon2` here.
1069-
// `isSubType` already takes care of dealiasing type
1075+
// `necessarySubType` already takes care of dealiasing type
10701076
// constructors when this can be done without affecting type
10711077
// inference, doing it here would not only prevent code from compiling
10721078
// but could also result in the wrong thing being inferred later, for example

0 commit comments

Comments
 (0)