Skip to content

Commit f437478

Browse files
committed
Better support type-heavy pattern matches
1 parent a738925 commit f437478

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
345345
val res = TypeComparer.provablyDisjoint(tp1, tp2)
346346

347347
if (res) Empty
348-
else if (tp1.isSingleton) Typ(tp1, true)
349-
else if (tp2.isSingleton) Typ(tp2, true)
350-
else Typ(AndType(tp1, tp2), true)
348+
else Typ(AndType(tp1, tp2), decomposed = true)
351349
}
352350
}
353351

@@ -594,11 +592,24 @@ class SpaceEngine(using Context) extends SpaceLogic {
594592
def decompose(tp: Type): List[Space] =
595593
tp.dealias match {
596594
case AndType(tp1, tp2) =>
597-
intersect(Typ(tp1, false), Typ(tp2, false)) match {
598-
case Or(spaces) => spaces.toList
599-
case Empty => Nil
600-
case space => List(space)
601-
}
595+
def decomposeComponent(tpA: Type, tpB: Type) =
596+
decompose(tpA).asInstanceOf[List[Typ]].flatMap {
597+
case Typ(tp, _) =>
598+
if tp <:< tpB then
599+
Typ(tp, decomposed = true) :: Nil
600+
else if tpB <:< tp then
601+
Typ(tpB, decomposed = true) :: Nil
602+
else
603+
intersectUnrelatedAtomicTypes(tp, tpB) match
604+
case Empty => Nil
605+
case space => List(space)
606+
}
607+
608+
if canDecompose(tp1) then
609+
decomposeComponent(tp1, tp2)
610+
else
611+
decomposeComponent(tp2, tp1)
612+
602613
case OrType(tp1, tp2) => List(Typ(tp1, true), Typ(tp2, true))
603614
case tp if tp.isRef(defn.BooleanClass) =>
604615
List(

tests/patmat/i12475.scala

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sealed trait Ty {
2+
type T
3+
}
4+
5+
class TUnit() extends Ty {
6+
type T = Unit
7+
}
8+
9+
case object TUnit extends TUnit()
10+
11+
final case class TFun(dom: Ty, cod: Ty) extends Ty {
12+
type T = dom.T => cod.T
13+
}
14+
15+
def default(ty: Ty): ty.T = (ty: ty.type & Ty) match {
16+
case a: (ty.type & TUnit) => (): a.T
17+
case a: (ty.type & TFun) =>
18+
val f = { (x: a.dom.T) => default(a.cod) }
19+
f: a.T
20+
}

0 commit comments

Comments
 (0)