summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-04-30 20:01:25 +0000
committerPaul Phillips <paulp@improving.org>2011-04-30 20:01:25 +0000
commitb4749d3b1afb1df236ec48fd3a773aab24a6f74d (patch)
tree81792bd4de8dfb8c2beb6ad1418880947fb6e371
parent793796eee0769926a3162d69dd23c282ca2d8ba4 (diff)
downloadscala-b4749d3b1afb1df236ec48fd3a773aab24a6f74d.tar.gz
scala-b4749d3b1afb1df236ec48fd3a773aab24a6f74d.tar.bz2
scala-b4749d3b1afb1df236ec48fd3a773aab24a6f74d.zip
Completely to my surprise, found that fixing al...
Completely to my surprise, found that fixing all those sequence issues revealed that the pattern matcher can catch a lot more inexhaustive cases than it has been catching. Fixed most of the inexhaustive matches in the compiler, which had become a bit warnier. No review.
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala4
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala9
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--test/files/neg/exhausting.check6
-rw-r--r--test/files/neg/patmatexhaust.check25
-rw-r--r--test/files/neg/patmatexhaust.flags1
-rw-r--r--test/files/neg/patmatexhaust.scala6
11 files changed, 40 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
index f29618c7cf..3d3097e497 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
@@ -321,9 +321,9 @@ abstract class ICodeCheckers {
}
}
- def popStack = { checkStack(1) ; popStackN(1) match { case List(x) => x } }
- def popStack2 = { checkStack(2) ; popStackN(2) match { case List(x, y) => (x, y) } }
- def popStack3 = { checkStack(3) ; popStackN(3) match { case List(x, y, z) => (x, y, z) } }
+ def popStack = { checkStack(1) ; (popStackN(1): @unchecked) match { case List(x) => x } }
+ def popStack2 = { checkStack(2) ; (popStackN(2): @unchecked) match { case List(x, y) => (x, y) } }
+ def popStack3 = { checkStack(3) ; (popStackN(3): @unchecked) match { case List(x, y, z) => (x, y, z) } }
/** Called by faux instruction LOAD_EXCEPTION to wipe out the stack. */
def clearStack() = {
diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
index e59d8c7858..c5c57938ca 100644
--- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala
@@ -136,7 +136,7 @@ trait MatrixAdditions extends ast.TreeDSL {
/** Exhaustiveness checking requires looking for sealed classes
* and if found, making sure all children are covered by a pattern.
*/
- class ExhaustivenessChecker(rep: Rep) {
+ class ExhaustivenessChecker(rep: Rep, matchPos: Position) {
val Rep(tvars, rows) = rep
import Flags.{ MUTABLE, ABSTRACT, SEALED }
@@ -201,7 +201,7 @@ trait MatrixAdditions extends ast.TreeDSL {
def check = {
def errMsg = (inexhaustives map mkMissingStr).mkString
if (inexhaustives.nonEmpty)
- cunit.warning(tvars.head.lhs.pos, "match is not exhaustive!\n" + errMsg)
+ cunit.warning(matchPos, "match is not exhaustive!\n" + errMsg)
rep
}
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 89ca99de86..fb617908c7 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -70,7 +70,11 @@ trait ParallelMatching extends ast.TreeDSL
val newRows = rows1 flatMap (_ expandAlternatives classifyPat)
if (rows1.length != newRows.length) make(roots1, newRows) // recursive call if any change
- else Rep(roots1, newRows).checkExhaustive
+ else {
+ val rep = Rep(roots1, newRows)
+ new ExhaustivenessChecker(rep, roots.head.sym.pos).check
+ rep
+ }
}
override def toString() = "MatchMatrix(%s) { %s }".format(matchResultType, indentAll(targets))
@@ -722,9 +726,6 @@ trait ParallelMatching extends ast.TreeDSL
lazy val guardedRest = if (guard.isEmpty) Rep(Nil, Nil) else make(tvars, rows.tail)
lazy val (defaults, others) = pats span (_.isDefault)
- /** Sealed classes. */
- def checkExhaustive = new ExhaustivenessChecker(this).check
-
/** Cut out the column containing the non-default pattern. */
class Cut(index: Int) {
/** The first two separate out the 'i'th pattern in each row from the remainder. */
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 750fdb3c3f..e0734e7f2e 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -173,9 +173,16 @@ trait Patterns extends ast.TreeDSL {
// 8.1.7 / 8.1.8 (unapply and unapplySeq calls)
case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
- override def simplify(pv: PatternVar) =
+ override def simplify(pv: PatternVar) = {
+ if (pv.sym hasFlag NO_EXHAUSTIVE) ()
+ else {
+ TRACE("Setting NO_EXHAUSTIVE on " + pv.sym + " due to extractor " + tree)
+ pv.sym setFlag NO_EXHAUSTIVE
+ }
+
if (pv.tpe <:< arg.tpe) this
else this rebindTo uaTyped
+ }
override def description = "Unapply(%s => %s)".format(necessaryType, resTypesString)
}
@@ -205,8 +212,6 @@ trait Patterns extends ast.TreeDSL {
override def necessaryType = if (nonStarPatterns.nonEmpty) consRef else listRef
override def simplify(pv: PatternVar) = {
- pv.sym setFlag NO_EXHAUSTIVE
-
if (pv.tpe <:< necessaryType)
foldedPatterns
else
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 36552894e5..007ab36e5e 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -458,7 +458,7 @@ abstract class Erasure extends AddInterfaces
else if (sym.name == nme.apply)
tp
else if (sym.name == nme.update)
- tp match {
+ (tp: @unchecked) match {
case MethodType(List(index, tvar), restpe) =>
MethodType(List(index.cloneSymbol.setInfo(erasure(index.tpe)), tvar),
erasedTypeRef(UnitClass))
@@ -987,7 +987,7 @@ abstract class Erasure extends AddInterfaces
case Apply(fn, args) =>
if (fn.symbol == Any_asInstanceOf)
- fn match {
+ (fn: @unchecked) match {
case TypeApply(Select(qual, _), List(targ)) =>
if (qual.tpe <:< targ.tpe) {
atPos(tree.pos) { Typed(qual, TypeTree(targ.tpe)) }
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index e837af42fd..9cfd497c76 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -271,11 +271,11 @@ abstract class LambdaLift extends InfoTransform {
case Some(ps) =>
val freeParams = ps map (p => ValDef(p) setPos tree.pos setType NoType)
tree match {
- case DefDef(mods, name, tparams, List(vparams), tpt, rhs) =>
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
val addParams = cloneSymbols(ps).map(_.setFlag(PARAM))
sym.updateInfo(
lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType)))
- treeCopy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs)
+ treeCopy.DefDef(tree, mods, name, tparams, List(vparamss.head ++ freeParams), tpt, rhs)
case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) =>
// Disabled attempt to to add getters to freeParams
// this does not work yet. Problem is that local symbols need local names
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2c89647c88..4a62c7c70d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2740,7 +2740,7 @@ trait Typers extends Modes {
fun1clazz,
List(selfsym.info, annClass.tpe))
- typed(func, mode, funcType) match {
+ (typed(func, mode, funcType): @unchecked) match {
case t @ Function(List(arg), rhs) =>
val subs =
new TreeSymSubstituter(List(arg.symbol),List(selfsym))
diff --git a/test/files/neg/exhausting.check b/test/files/neg/exhausting.check
index d3f2251f79..0bef21e077 100644
--- a/test/files/neg/exhausting.check
+++ b/test/files/neg/exhausting.check
@@ -2,7 +2,7 @@ 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
@@ -17,7 +17,7 @@ exhausting.scala:31: error: match is not exhaustive!
missing combination Bar2 Bar2
def fail4[T <: AnyRef](xx: (Foo[T], Foo[T])) = xx match {
- ^
+ ^
exhausting.scala:36: error: match is not exhaustive!
missing combination Bar1 Bar2
missing combination Bar1 Bar3
@@ -25,5 +25,5 @@ missing combination Bar2 Bar1
missing combination Bar2 Bar2
def fail5[T](xx: (Foo[T], Foo[T])) = xx match {
- ^
+ ^
5 errors found
diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check
index 83c4279b0a..8aa9238d2e 100644
--- a/test/files/neg/patmatexhaust.check
+++ b/test/files/neg/patmatexhaust.check
@@ -1,37 +1,38 @@
-patmatexhaust.scala:7: warning: match is not exhaustive!
+patmatexhaust.scala:7: error: match is not exhaustive!
missing combination Baz
def ma1(x:Foo) = x match {
^
-patmatexhaust.scala:11: warning: match is not exhaustive!
+patmatexhaust.scala:11: error: match is not exhaustive!
missing combination Bar
def ma2(x:Foo) = x match {
^
-patmatexhaust.scala:23: warning: match is not exhaustive!
+patmatexhaust.scala:23: error: match is not exhaustive!
missing combination Kult Kult
missing combination Qult Qult
def ma3(x:Mult) = (x,x) match { // not exhaustive
- ^
-patmatexhaust.scala:49: warning: match is not exhaustive!
+ ^
+patmatexhaust.scala:49: error: match is not exhaustive!
missing combination Gp
missing combination Gu
def ma4(x:Deep) = x match { // missing cases: Gu, Gp
^
-patmatexhaust.scala:53: warning: match is not exhaustive!
+patmatexhaust.scala:53: error: match is not exhaustive!
missing combination Gp
def ma5(x:Deep) = x match { // Gp
^
-patmatexhaust.scala:75: warning: match is not exhaustive!
+patmatexhaust.scala:59: error: match is not exhaustive!
+missing combination Nil
+
+ def ma6() = List(1,2) match { // give up
+ ^
+patmatexhaust.scala:75: error: match is not exhaustive!
missing combination B
def ma9(x: B) = x match {
^
-patmatexhaust.scala:92: error: unreachable code
- case 1 =>
- ^
-6 warnings found
-one error found
+7 errors found
diff --git a/test/files/neg/patmatexhaust.flags b/test/files/neg/patmatexhaust.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/patmatexhaust.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/patmatexhaust.scala b/test/files/neg/patmatexhaust.scala
index 4a66649a18..d49c4b207b 100644
--- a/test/files/neg/patmatexhaust.scala
+++ b/test/files/neg/patmatexhaust.scala
@@ -86,10 +86,4 @@ class TestSealedExhaustive { // compile only
case C4() => true
case C2 | C6 => true
}
-
- def redundant() = 1 match { // include this otherwise script won't test this in files/neg
- case 1 =>
- case 1 =>
- }
-
}