diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala index 156551519cb9..47b2d3a69a10 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala @@ -228,7 +228,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { resKind } - def genPrimitiveOp(tree: Apply, expectedType: BType): BType = tree match { + def genPrimitiveOp(tree: Apply, expectedType: BType): BType = (tree: @unchecked) match { case Apply(fun @ DesugaredSelect(receiver, _), _) => val sym = tree.symbol @@ -610,7 +610,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder { } } - def genTypeApply(t: TypeApply): BType = t match { + def genTypeApply(t: TypeApply): BType = (t: @unchecked) match { case TypeApply(fun@DesugaredSelect(obj, _), targs) => val sym = fun.symbol diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala index 04425b524b93..d326bcfa242a 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala @@ -27,7 +27,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder { */ abstract class SyncAndTryBuilder(cunit: CompilationUnit) extends PlainBodyBuilder(cunit) { - def genSynchronized(tree: Apply, expectedType: BType): BType = tree match { + def genSynchronized(tree: Apply, expectedType: BType): BType = (tree: @unchecked) match { case Apply(TypeApply(fun, _), args) => val monitor = locals.makeLocal(ObjectReference, "monitor", defn.ObjectType, tree.span) val monCleanup = new asm.Label diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala index 8f4aa6af8783..90b2b4f4cabf 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala @@ -121,7 +121,7 @@ class StringInterpolatorOpt extends MiniPhase { (sym.name == nme.f && sym.eq(defn.StringContext_f)) || (sym.name == nme.s && sym.eq(defn.StringContext_s)) if (isInterpolatedMethod) - tree match { + (tree: @unchecked) match { case StringContextIntrinsic(strs: List[Literal], elems: List[Tree]) => val stri = strs.iterator val elemi = elems.iterator diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index bcb021af7b76..b6993735ac89 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -791,16 +791,18 @@ class SpaceEngine(using Context) extends SpaceLogic { def isCheckable(tp: Type): Boolean = !tp.hasAnnotation(defn.UncheckedAnnot) && { val tpw = tp.widen.dealias + val classSym = tpw.classSymbol ctx.settings.YcheckAllPatmat.value || - tpw.typeSymbol.is(Sealed) || + classSym.is(Sealed) || tpw.isInstanceOf[OrType] || (tpw.isInstanceOf[AndType] && { val and = tpw.asInstanceOf[AndType] isCheckable(and.tp1) || isCheckable(and.tp2) }) || tpw.isRef(defn.BooleanClass) || - tpw.typeSymbol.isAllOf(JavaEnumTrait) || - (defn.isTupleType(tpw) && tpw.argInfos.exists(isCheckable(_))) + classSym.isAllOf(JavaEnumTrait) || + (defn.isProductSubType(tpw) && classSym.is(Case) + && productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_))) } val res = isCheckable(sel.tpe) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 2d30b925a7eb..f8e9143c1fc0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -990,7 +990,7 @@ trait Applications extends Compatibility { * { val xs = es; e' = e' + args } */ def typedOpAssign(using Context): Tree = { - val (lhs1, name, rhss) = tree match + val (lhs1, name, rhss) = (tree: @unchecked) match case Apply(Select(lhs, name), rhss) => (typedExpr(lhs), name, rhss) case Apply(untpd.TypedSplice(Select(lhs1, name)), rhss) => (lhs1, name, rhss) val liftedDefs = new mutable.ListBuffer[Tree] diff --git a/tests/neg-custom-args/isInstanceOf/enum-approx2.scala b/tests/neg-custom-args/isInstanceOf/enum-approx2.scala index 8350f9cf4b9c..516b765ec64b 100644 --- a/tests/neg-custom-args/isInstanceOf/enum-approx2.scala +++ b/tests/neg-custom-args/isInstanceOf/enum-approx2.scala @@ -5,5 +5,6 @@ class Test { def eval(e: Fun[Int, Int]) = e match { case Fun(x: Fun[Int, Double]) => ??? // error case Fun(x: Exp[Int => String]) => ??? // error + case _ => } } \ No newline at end of file diff --git a/tests/patmat/i12337.check b/tests/patmat/i12337.check new file mode 100644 index 000000000000..2b314017a6dd --- /dev/null +++ b/tests/patmat/i12337.check @@ -0,0 +1,2 @@ +8: Pattern Match Exhaustivity: Foo(Inactive) +17: Pattern Match Exhaustivity: Foo(Status.Active(_)) diff --git a/tests/patmat/i12337.scala b/tests/patmat/i12337.scala new file mode 100644 index 000000000000..efa3e04168d6 --- /dev/null +++ b/tests/patmat/i12337.scala @@ -0,0 +1,26 @@ +sealed trait Status +object Status { + case class Active(since: Int) extends Status + case object Inactive extends Status +} + +case class Foo(status: Status) +def bar(foo: Foo): Unit = foo match { + case Foo(Status.Active(since)) => + println(s"active since $since") +} +// Expected: +// warning: match may not be exhaustive. +// It would fail on the following input: Foo(Inactive) +// def bar(foo: Foo): Unit = foo match { + +def baz(foo: Foo): Unit = foo match { + case Foo(Status.Active(2000)) => + println("active since 2000") + case Foo(Status.Inactive) => + println("inactive") +} +// Expected: +// warning: match may not be exhaustive. +// It would fail on the following input: Foo(Active((x: Int forSome x not in 2000))) +// def baz(foo: Foo): Unit = foo match { \ No newline at end of file