From 6b75f5b76839ebb61acca1048e0d3cf47c695d36 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 3 Apr 2018 11:08:43 +0200 Subject: [PATCH] Fix #4225: always check redundant cases except for @uncheck --- .../dotty/tools/dotc/transform/PatternMatcher.scala | 7 ++----- .../dotty/tools/dotc/transform/patmat/Space.scala | 12 ++++++++---- tests/patmat/i4225.check | 1 + tests/patmat/i4225.scala | 12 ++++++++++++ 4 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 tests/patmat/i4225.check create mode 100644 tests/patmat/i4225.scala diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 8fa12812799a..5d2ad1e1274c 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -33,11 +33,8 @@ class PatternMatcher extends MiniPhase { // check exhaustivity and unreachability val engine = new patmat.SpaceEngine - - if (engine.checkable(tree)) { - engine.checkExhaustivity(tree) - engine.checkRedundancy(tree) - } + engine.checkExhaustivity(tree) + engine.checkRedundancy(tree) translated.ensureConforms(tree.tpe) } diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index da4f0feb2f8a..1efee9130cef 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -839,7 +839,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { flatten(s).map(doShow(_, false)).distinct.mkString(", ") } - def checkable(tree: Match): Boolean = { + private def exhaustivityCheckable(sel: Tree): Boolean = { // Possible to check everything, but be compatible with scalac by default def isCheckable(tp: Type): Boolean = !tp.hasAnnotation(defn.UncheckedAnnot) && { @@ -857,9 +857,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { (defn.isTupleType(tpw) && tpw.argInfos.exists(isCheckable(_))) } - val Match(sel, cases) = tree val res = isCheckable(sel.tpe) - debug.println(s"checkable: ${sel.show} = $res") + debug.println(s"exhaustivity checkable: ${sel.show} = $res") res } @@ -877,6 +876,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { val Match(sel, cases) = _match val selTyp = sel.tpe.widen.dealias + if (!exhaustivityCheckable(sel)) return val patternSpace = cases.map({ x => val space = project(x.pat) @@ -894,11 +894,15 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { ctx.warning(PatternMatchExhaustivity(show(Or(uncovered))), sel.pos) } + private def redundancyCheckable(sel: Tree): Boolean = + !sel.tpe.hasAnnotation(defn.UncheckedAnnot) + def checkRedundancy(_match: Match): Unit = { val Match(sel, cases) = _match - // ignore selector type for now val selTyp = sel.tpe.widen.dealias + if (!redundancyCheckable(sel)) return + (0 until cases.length).foreach { i => // in redundancy check, take guard as false in order to soundly approximate val prevs = diff --git a/tests/patmat/i4225.check b/tests/patmat/i4225.check new file mode 100644 index 000000000000..024161675702 --- /dev/null +++ b/tests/patmat/i4225.check @@ -0,0 +1 @@ +10: Match case Unreachable diff --git a/tests/patmat/i4225.scala b/tests/patmat/i4225.scala new file mode 100644 index 000000000000..79a117187af7 --- /dev/null +++ b/tests/patmat/i4225.scala @@ -0,0 +1,12 @@ +object Bar { + def unapply(x: Int): Some[Int] = + Some(0) +} + +object Test { + def test(x: Int) = + x match { + case Bar(a) => a + case _ => x // should be unreachable + } +}