Skip to content

Commit

Permalink
Fix missing case in isSubspace, which broke reachablility (scala#18326)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Aug 3, 2023
2 parents e4480a6 + d6e9efd commit 6a6ee08
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,11 @@ object SpaceEngine {
|| canDecompose(b) && isSubspace(a, Or(decompose(b)))
case (Prod(tp1, _, _), Typ(tp2, _)) =>
isSubType(tp1, tp2)
case (Typ(tp1, _), Prod(tp2, fun, ss)) =>
case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) =>
isSubType(tp1, tp2)
&& covers(fun, tp1, ss.length)
&& isSubspace(Prod(tp2, fun, signature(fun, tp1, ss.length).map(Typ(_, false))), b)
|| canDecompose(a) && isSubspace(Or(decompose(a)), b)
case (Prod(_, fun1, ss1), Prod(_, fun2, ss2)) =>
isSameUnapply(fun1, fun2) && ss1.lazyZip(ss2).forall(isSubspace)
}
Expand Down Expand Up @@ -597,7 +598,7 @@ object SpaceEngine {
}

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

/** Decompose a type into subspaces -- assume the type can be decomposed */
def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) {
Expand Down
4 changes: 4 additions & 0 deletions tests/patmat/i18118.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
12: Pattern Match
21: Pattern Match
32: Pattern Match
41: Pattern Match
41 changes: 41 additions & 0 deletions tests/patmat/i18118.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// scalac: -Werror

object O1:
sealed trait A
case class B() extends A
case class C() extends A


def bigMatch(x: A) = x match
case B() =>
case C() =>
case _ => // error

object O2:
sealed trait A
case class B() extends A


def bigMatch(x: A) = x match
case B() =>
case _ => // error // was: no "unreachable but for null" warning

object O3:
sealed trait A
case class B() extends A
case class C() extends A


def bigMatch(x: A) = x match
case _: B =>
case _: C =>
case _ => // error

object O4:
sealed trait A
case class B() extends A


def bigMatch(x: A) = x match
case _: B =>
case _ => // error

0 comments on commit 6a6ee08

Please sign in to comment.