Skip to content

Commit 10b5ca0

Browse files
committed
Fix #12358: Avoid spurious unions in simplification
And be more lazier in product subtraction
1 parent f4d139d commit 10b5ca0

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,17 @@ trait SpaceLogic {
113113
/** Display space in string format */
114114
def show(sp: Space): String
115115

116-
/** Simplify space using the laws, there's no nested union after simplify */
116+
/** Simplify space such that a space equal to `Empty` becomes `Empty` */
117117
def simplify(space: Space)(using Context): Space = trace(s"simplify ${show(space)} --> ", debug, x => show(x.asInstanceOf[Space]))(space match {
118118
case Prod(tp, fun, spaces) =>
119-
val sp = Prod(tp, fun, spaces.map(simplify(_)))
120-
if (sp.params.contains(Empty)) Empty
119+
val sps = spaces.map(simplify(_))
120+
if (sps.contains(Empty)) Empty
121121
else if (canDecompose(tp) && decompose(tp).isEmpty) Empty
122-
else sp
122+
else Prod(tp, fun, sps)
123123
case Or(spaces) =>
124124
val spaces2 = spaces.map(simplify(_)).filter(_ != Empty)
125125
if spaces2.isEmpty then Empty
126+
else if spaces2.lengthCompare(1) == 0 then spaces2.head
126127
else Or(spaces2)
127128
case Typ(tp, _) =>
128129
if (canDecompose(tp) && decompose(tp).isEmpty) Empty
@@ -243,10 +244,10 @@ trait SpaceLogic {
243244
tryDecompose1(tp1)
244245
else
245246
a
246-
case (_, Or(ss)) =>
247-
ss.foldLeft(a)(minus)
248247
case (Or(ss), _) =>
249248
Or(ss.map(minus(_, b)))
249+
case (_, Or(ss)) =>
250+
ss.foldLeft(a)(minus)
250251
case (Prod(tp1, fun, ss), Typ(tp2, _)) =>
251252
// uncovered corner case: tp2 :< tp1, may happen when inheriting case class
252253
if (isSubType(tp1, tp2))
@@ -272,7 +273,10 @@ trait SpaceLogic {
272273
else if cache.forall(sub => isSubspace(sub, Empty)) then Empty
273274
else
274275
// `(_, _, _) - (Some, None, _)` becomes `(None, _, _) | (_, Some, _) | (_, _, Empty)`
275-
Or(LazyList(range: _*).map { i => Prod(tp1, fun1, ss1.updated(i, sub(i))) })
276+
val spaces = LazyList(range: _*).flatMap { i =>
277+
flatten(sub(i)).map(s => Prod(tp1, fun1, ss1.updated(i, s)))
278+
}
279+
Or(spaces)
276280
}
277281
}
278282
}

tests/patmat/i12358.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
def foo(x: List[Int]): Unit =
3+
x match
4+
// case x1 :: x2 :: x3 :: x4 :: x5 :: x6 :: x7 :: x8 :: x9 :: x10 :: x11 :: x12 :: x13 :: x14 :: Nil =>
5+
case x1 :: x2 :: x3 :: x4 :: x5 :: x6 :: x7 :: x8 :: x9 :: x10 :: x11 :: x12 :: x13 :: x14 :: x15 :: x16 :: x17 :: x18 :: x19 :: x20 :: x21 :: x22 :: Nil =>

0 commit comments

Comments
 (0)