diff options
author | Paul Phillips <paulp@improving.org> | 2010-10-05 02:59:06 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-10-05 02:59:06 +0000 |
commit | 4afd17d6d309ba1d64979ee9078edebc5d8e035e (patch) | |
tree | 1eeeb455d8a54c95c5821649a2fec7ef321a9943 | |
parent | 74a0c96db07a3bef246bcc197cbe545b2a1eeee7 (diff) | |
download | scala-4afd17d6d309ba1d64979ee9078edebc5d8e035e.tar.gz scala-4afd17d6d309ba1d64979ee9078edebc5d8e035e.tar.bz2 scala-4afd17d6d309ba1d64979ee9078edebc5d8e035e.zip |
Massively simplified the exhaustiveness checker...
Massively simplified the exhaustiveness checker with no measurable loss
of fidelity. I might be the only one who can be unsurprised by such a
bloody diff: anyone else would rightly say "how on earth..." No review.
-rw-r--r-- | src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala | 27 | ||||
-rw-r--r-- | test/files/neg/exhausting.check | 24 | ||||
-rw-r--r-- | test/files/neg/exhausting.flags | 1 | ||||
-rw-r--r-- | test/files/neg/exhausting.scala | 40 |
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 = { + + } +} |