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. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@23191 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
b8cde80af3
commit
db8f536c20
|
@ -145,7 +145,7 @@ trait MatrixAdditions extends ast.TreeDSL
|
|||
self: MatchMatrix =>
|
||||
|
||||
import self.context._
|
||||
|
||||
|
||||
/** Exhaustiveness checking requires looking for sealed classes
|
||||
* and if found, making sure all children are covered by a pattern.
|
||||
*/
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
-Xfatal-warnings
|
|
@ -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 = {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue