Skip to content

Commit 87a501c

Browse files
committed
Make matchCases tail-recursive
1 parent 51d8cab commit 87a501c

File tree

1 file changed

+36
-35
lines changed

1 file changed

+36
-35
lines changed

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

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,45 +2134,46 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
21342134
}
21352135
}
21362136

2137-
var result: Type = NoType
2138-
var remainingCases = cases
2139-
while (!remainingCases.isEmpty) {
2140-
val (cas :: cass) = remainingCases
2141-
remainingCases = cass
2142-
val saved = constraint
2143-
try {
2144-
inFrozenConstraint {
2145-
val cas1 = cas match {
2146-
case cas: HKTypeLambda =>
2147-
caseLambda = constrained(cas)
2148-
caseLambda.resultType
2137+
/** Match a single case.
2138+
* @return Some(tp) if the match succeeds with type `tp`
2139+
* Some(NoType) if the match fails, and there is an overlap between pattern and scrutinee
2140+
* None if the match fails and we should consider the following cases
2141+
* because scrutinee and pattern do not overlap
2142+
*/
2143+
def matchCase(cas: Type): Option[Type] = {
2144+
val cas1 = cas match {
2145+
case cas: HKTypeLambda =>
2146+
caseLambda = constrained(cas)
2147+
caseLambda.resultType
2148+
case _ =>
2149+
cas
2150+
}
2151+
val defn.FunctionOf(pat :: Nil, body, _, _) = cas1
2152+
if (isSubType(scrut, pat))
2153+
// `scrut` is a subtype of `pat`: *It's a Match!*
2154+
Some {
2155+
caseLambda match {
2156+
case caseLambda: HKTypeLambda =>
2157+
val instances = paramInstances(new Array(caseLambda.paramNames.length), pat)
2158+
instantiateParams(instances)(body)
21492159
case _ =>
2150-
cas
2151-
}
2152-
val defn.FunctionOf(pat :: Nil, body, _, _) = cas1
2153-
if (isSubType(scrut, pat)) {
2154-
// `scrut` is a subtype of `pat`: *It's a Match!*
2155-
result = caseLambda match {
2156-
case caseLambda: HKTypeLambda =>
2157-
val instances = paramInstances(new Array(caseLambda.paramNames.length), pat)
2158-
instantiateParams(instances)(body)
2159-
case _ =>
2160-
body
2161-
}
2162-
remainingCases = Nil
2163-
} else if (!intersecting(scrut, pat)) {
2164-
// We found a proof that `scrut` and `pat` are incompatible.
2165-
// The search continues.
2166-
} else {
2167-
// We are stuck: this match type instanciation is irreducible.
2168-
result = NoType
2169-
remainingCases = Nil
2160+
body
21702161
}
21712162
}
2172-
}
2173-
finally constraint = saved
2163+
else if (intersecting(scrut, pat))
2164+
Some(NoType)
2165+
else
2166+
// We found a proof that `scrut` and `pat` are incompatible.
2167+
// The search continues.
2168+
None
21742169
}
2175-
result
2170+
2171+
def recur(cases: List[Type]) = cases match {
2172+
case cas :: cases1 => matchCase(cas).getOrElse(recur(cases1))
2173+
case Nil => NoType
2174+
}
2175+
2176+
inFrozenConstraint(recur(cases))
21762177
}
21772178
}
21782179

0 commit comments

Comments
 (0)