Skip to content

Commit 6a6ee08

Browse files
authored
Fix missing case in isSubspace, which broke reachablility (#18326)
2 parents e4480a6 + d6e9efd commit 6a6ee08

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,11 @@ object SpaceEngine {
193193
|| canDecompose(b) && isSubspace(a, Or(decompose(b)))
194194
case (Prod(tp1, _, _), Typ(tp2, _)) =>
195195
isSubType(tp1, tp2)
196-
case (Typ(tp1, _), Prod(tp2, fun, ss)) =>
196+
case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) =>
197197
isSubType(tp1, tp2)
198198
&& covers(fun, tp1, ss.length)
199199
&& isSubspace(Prod(tp2, fun, signature(fun, tp1, ss.length).map(Typ(_, false))), b)
200+
|| canDecompose(a) && isSubspace(Or(decompose(a)), b)
200201
case (Prod(_, fun1, ss1), Prod(_, fun2, ss2)) =>
201202
isSameUnapply(fun1, fun2) && ss1.lazyZip(ss2).forall(isSubspace)
202203
}
@@ -597,7 +598,7 @@ object SpaceEngine {
597598
}
598599

599600
/** Whether the extractor covers the given type */
600-
def covers(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): Boolean =
601+
def covers(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): Boolean = trace(i"covers($unapp, $scrutineeTp, $argLen)") {
601602
SpaceEngine.isIrrefutable(unapp, argLen)
602603
|| unapp.symbol == defn.TypeTest_unapply && {
603604
val AppliedType(_, _ :: tp :: Nil) = unapp.prefix.widen.dealias: @unchecked
@@ -607,6 +608,7 @@ object SpaceEngine {
607608
val AppliedType(_, tp :: Nil) = unapp.prefix.widen.dealias: @unchecked
608609
scrutineeTp <:< tp
609610
}
611+
}
610612

611613
/** Decompose a type into subspaces -- assume the type can be decomposed */
612614
def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) {

tests/patmat/i18118.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
12: Pattern Match
2+
21: Pattern Match
3+
32: Pattern Match
4+
41: Pattern Match

tests/patmat/i18118.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// scalac: -Werror
2+
3+
object O1:
4+
sealed trait A
5+
case class B() extends A
6+
case class C() extends A
7+
8+
9+
def bigMatch(x: A) = x match
10+
case B() =>
11+
case C() =>
12+
case _ => // error
13+
14+
object O2:
15+
sealed trait A
16+
case class B() extends A
17+
18+
19+
def bigMatch(x: A) = x match
20+
case B() =>
21+
case _ => // error // was: no "unreachable but for null" warning
22+
23+
object O3:
24+
sealed trait A
25+
case class B() extends A
26+
case class C() extends A
27+
28+
29+
def bigMatch(x: A) = x match
30+
case _: B =>
31+
case _: C =>
32+
case _ => // error
33+
34+
object O4:
35+
sealed trait A
36+
case class B() extends A
37+
38+
39+
def bigMatch(x: A) = x match
40+
case _: B =>
41+
case _ => // error

0 commit comments

Comments
 (0)