diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 45c1444879db..301f80960d8f 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -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) } @@ -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 @@ -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) { diff --git a/tests/patmat/i18118.check b/tests/patmat/i18118.check new file mode 100644 index 000000000000..8861eb273fb9 --- /dev/null +++ b/tests/patmat/i18118.check @@ -0,0 +1,4 @@ +12: Pattern Match +21: Pattern Match +32: Pattern Match +41: Pattern Match diff --git a/tests/patmat/i18118.scala b/tests/patmat/i18118.scala new file mode 100644 index 000000000000..c51d736d3db3 --- /dev/null +++ b/tests/patmat/i18118.scala @@ -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