summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala27
-rw-r--r--test/files/neg/exhausting.check24
-rw-r--r--test/files/neg/exhausting.flags1
-rw-r--r--test/files/neg/exhausting.scala40
4 files changed, 68 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
index fbfe00d2c1..e2d26abf1f 100644
--- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
@@ -155,32 +155,11 @@ trait MatrixAdditions extends ast.TreeDSL
import Flags.{ MUTABLE, ABSTRACT, SEALED, TRANS_FLAG }
private case class Combo(index: Int, sym: Symbol) {
+ val isBaseClass = sym.tpe.baseClasses.toSet
+
// is this combination covered by the given pattern?
def isCovered(p: Pattern) = {
- def cmpSymbols(t1: Type, t2: Type) = t1.typeSymbol eq t2.typeSymbol
- def coversSym = {
- val tpe = decodedEqualsType(p.tpe)
- lazy val lmoc = sym.companionModule
- val symtpe =
- if ((sym hasFlag Flags.MODULE) && (lmoc ne NoSymbol))
- singleType(sym.tpe.prefix, lmoc) // e.g. None, Nil
- else sym.tpe
-
- /** Note to Martin should you come through this way: this
- * logic looks way overcomplicated for the intention, but a little
- * experimentation showed that at least most of it is serving
- * some necessary purpose. It doesn't seem like much more than
- * "sym.tpe matchesPattern tpe" ought to be necessary though.
- *
- * For the time being I tacked the matchesPattern test onto the
- * end to address #3097.
- */
- (tpe.typeSymbol == sym) ||
- (symtpe <:< tpe) ||
- (symtpe.parents exists (x => cmpSymbols(x, tpe))) || // e.g. Some[Int] <: Option[&b]
- ((tpe.prefix memberType sym) <:< tpe) || // outer, see combinator.lexical.Scanner
- (symtpe matchesPattern tpe)
- }
+ def coversSym = isBaseClass(decodedEqualsType(p.tpe).typeSymbol)
cond(p.tree) {
case _: UnApply | _: ArrayValue => true
diff --git a/test/files/neg/exhausting.check b/test/files/neg/exhausting.check
new file mode 100644
index 0000000000..6383a6eaca
--- /dev/null
+++ b/test/files/neg/exhausting.check
@@ -0,0 +1,24 @@
+exhausting.scala:20: error: match is not exhaustive!
+missing combination * Nil
+
+ def fail1[T](xs: List[T]) = xs match {
+ ^
+exhausting.scala:24: error: match is not exhaustive!
+missing combination Nil
+
+ def fail2[T](xs: List[T]) = xs match {
+ ^
+exhausting.scala:27: error: match is not exhaustive!
+missing combination Bar3
+
+ def fail3[T](x: Foo[T]) = x match {
+ ^
+exhausting.scala:31: error: match is not exhaustive!
+missing combination Bar1 Bar2
+missing combination Bar1 Bar3
+missing combination Bar2 Bar1
+missing combination Bar2 Bar2
+
+ def fail4[T](xx: (Foo[T], Foo[T])) = xx match {
+ ^
+four errors found
diff --git a/test/files/neg/exhausting.flags b/test/files/neg/exhausting.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/exhausting.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/exhausting.scala b/test/files/neg/exhausting.scala
new file mode 100644
index 0000000000..8b1ea817e4
--- /dev/null
+++ b/test/files/neg/exhausting.scala
@@ -0,0 +1,40 @@
+object Test {
+ sealed abstract class Foo[T]
+ case object Bar1 extends Foo[Int]
+ case object Bar2 extends Foo[String]
+ case object Bar3 extends Foo[Any]
+
+ def ex1[T](xs: List[T]) = xs match {
+ case ys: List[_] => "ok"
+ }
+ def ex2[T](xx: (Foo[T], Foo[T])) = xx match {
+ case (Bar1, Bar1) => ()
+ case (_, Bar1) => ()
+ case (_, Bar3) => ()
+ case (_, Bar2) => ()
+ }
+ def ex3[T](xx: (Foo[T], Foo[T])) = xx match {
+ case (_: Foo[_], _: Foo[_]) => ()
+ }
+
+ def fail1[T](xs: List[T]) = xs match {
+ case Nil => "ok"
+ case x :: y :: Nil => "ok"
+ }
+ def fail2[T](xs: List[T]) = xs match {
+ case _ :: _ => "ok"
+ }
+ def fail3[T](x: Foo[T]) = x match {
+ case Bar1 => "ok"
+ case Bar2 => "ok"
+ }
+ def fail4[T](xx: (Foo[T], Foo[T])) = xx match {
+ case (Bar1, Bar1) => ()
+ case (Bar2, Bar3) => ()
+ case (Bar3, _) => ()
+ }
+
+ def main(args: Array[String]): Unit = {
+
+ }
+}