From fc3e02b0817f0f2157fc5eb6f4187846546cafa0 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 3 Apr 2018 13:39:47 +0200 Subject: [PATCH 1/3] Fix #4226: allow infallible boolean extractors to return `true` --- .../tools/dotc/transform/PatternMatcher.scala | 2 +- .../dotty/tools/dotc/transform/patmat/Space.scala | 1 + .../src/dotty/tools/dotc/typer/Applications.scala | 2 +- tests/patmat/i4226.check | 1 + tests/patmat/i4226.scala | 15 +++++++++++++++ tests/pos/i4226.scala | 15 +++++++++++++++ 6 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/patmat/i4226.check create mode 100644 tests/patmat/i4226.scala create mode 100644 tests/pos/i4226.scala diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 5d2ad1e1274c..9b10f88e4a17 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -289,7 +289,7 @@ object PatternMatcher { if (isSyntheticScala2Unapply(unapp.symbol) && caseAccessors.length == args.length) matchArgsPlan(caseAccessors.map(ref(scrutinee).select(_)), args, onSuccess) - else if (unapp.tpe.isRef(defn.BooleanClass)) + else if (unapp.tpe.widenSingleton.isRef(defn.BooleanClass)) TestPlan(GuardTest, unapp, unapp.pos, onSuccess, onFailure) else { letAbstract(unapp) { unappResult => diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index e3f064031758..20057a560016 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -309,6 +309,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic { def irrefutable(unapp: Tree): Boolean = { // TODO: optionless patmat unapp.tpe.widen.finalResultType.isRef(scalaSomeClass) || + unapp.tpe.widen.finalResultType =:= ConstantType(Constant(true)) || (unapp.symbol.is(Synthetic) && unapp.symbol.owner.linkedClass.is(Case)) || productArity(unapp.tpe.widen.finalResultType) > 0 } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 83f8b88d86df..7d77920e8741 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -114,7 +114,7 @@ object Applications { productSelectorTypes(unapplyResult) else if (isGetMatch(unapplyResult, pos)) getUnapplySelectors(getTp, args, pos) - else if (unapplyResult isRef defn.BooleanClass) + else if (unapplyResult.widenSingleton isRef defn.BooleanClass) Nil else if (defn.isProductSubType(unapplyResult)) productSelectorTypes(unapplyResult) diff --git a/tests/patmat/i4226.check b/tests/patmat/i4226.check new file mode 100644 index 000000000000..9d5e9110945e --- /dev/null +++ b/tests/patmat/i4226.check @@ -0,0 +1 @@ +11: Pattern Match Exhaustivity: Just(_) diff --git a/tests/patmat/i4226.scala b/tests/patmat/i4226.scala new file mode 100644 index 000000000000..ad75c4d1236c --- /dev/null +++ b/tests/patmat/i4226.scala @@ -0,0 +1,15 @@ +sealed abstract class Maybe[A] +final case class Just[A](a: A) extends Maybe[A] +class Empty[A] extends Maybe[A] +object Empty { + def apply[A](): Maybe[A] = new Empty[A] + def unapply[A](e: Empty[A]): true = true +} + +object Test { + val a: Maybe[Int] = Just(2) + def main(args: Array[String]): Unit = a match { + case Just(2) => true + case Empty() => + } +} diff --git a/tests/pos/i4226.scala b/tests/pos/i4226.scala new file mode 100644 index 000000000000..ad75c4d1236c --- /dev/null +++ b/tests/pos/i4226.scala @@ -0,0 +1,15 @@ +sealed abstract class Maybe[A] +final case class Just[A](a: A) extends Maybe[A] +class Empty[A] extends Maybe[A] +object Empty { + def apply[A](): Maybe[A] = new Empty[A] + def unapply[A](e: Empty[A]): true = true +} + +object Test { + val a: Maybe[Int] = Just(2) + def main(args: Array[String]): Unit = a match { + case Just(2) => true + case Empty() => + } +} From 189fbc198c2464ccb13ce2bcb91dd934e3ce4354 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 3 Apr 2018 17:36:49 +0200 Subject: [PATCH 2/3] add test case for unapply return `false` --- tests/pos/i4226b.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/pos/i4226b.scala diff --git a/tests/pos/i4226b.scala b/tests/pos/i4226b.scala new file mode 100644 index 000000000000..d489b1d5b8f0 --- /dev/null +++ b/tests/pos/i4226b.scala @@ -0,0 +1,15 @@ +sealed abstract class Maybe[A] +final case class Just[A](a: A) extends Maybe[A] +class Empty[A] extends Maybe[A] +object Empty { + def apply[A](): Maybe[A] = new Empty[A] + def unapply[A](e: Empty[A]): false = false +} + +object Test { + val a: Maybe[Int] = Just(2) + def main(args: Array[String]): Unit = a match { + case Just(2) => true + case Empty() => + } +} From f1b8cdaeb80bf5797e667a04aa4064ca8e698570 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 3 Apr 2018 18:04:13 +0200 Subject: [PATCH 3/3] remove duplicate tests --- tests/patmat/i4226b.check | 1 + tests/{pos => patmat}/i4226b.scala | 0 tests/pos/i4226.scala | 15 --------------- 3 files changed, 1 insertion(+), 15 deletions(-) create mode 100644 tests/patmat/i4226b.check rename tests/{pos => patmat}/i4226b.scala (100%) delete mode 100644 tests/pos/i4226.scala diff --git a/tests/patmat/i4226b.check b/tests/patmat/i4226b.check new file mode 100644 index 000000000000..1528dd515904 --- /dev/null +++ b/tests/patmat/i4226b.check @@ -0,0 +1 @@ +11: Pattern Match Exhaustivity: _: Empty, Just(_) diff --git a/tests/pos/i4226b.scala b/tests/patmat/i4226b.scala similarity index 100% rename from tests/pos/i4226b.scala rename to tests/patmat/i4226b.scala diff --git a/tests/pos/i4226.scala b/tests/pos/i4226.scala deleted file mode 100644 index ad75c4d1236c..000000000000 --- a/tests/pos/i4226.scala +++ /dev/null @@ -1,15 +0,0 @@ -sealed abstract class Maybe[A] -final case class Just[A](a: A) extends Maybe[A] -class Empty[A] extends Maybe[A] -object Empty { - def apply[A](): Maybe[A] = new Empty[A] - def unapply[A](e: Empty[A]): true = true -} - -object Test { - val a: Maybe[Int] = Just(2) - def main(args: Array[String]): Unit = a match { - case Just(2) => true - case Empty() => - } -}