summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala7
-rw-r--r--test/files/pos/patmat-suppress.flags1
-rw-r--r--test/files/pos/patmat-suppress.scala159
5 files changed, 167 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 8650f6ef90..3223d99ad0 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -761,12 +761,12 @@ trait MatchAnalysis extends MatchApproximation {
}
def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, suppression: Suppression): Unit = {
- if (!suppression.unreachable) {
+ if (!suppression.suppressUnreachable) {
unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
reportUnreachable(cases(caseIndex).last.pos)
}
}
- if (!suppression.exhaustive) {
+ if (!suppression.suppressExhaustive) {
val counterExamples = exhaustive(prevBinder, cases, pt)
if (counterExamples.nonEmpty)
reportMissingCases(prevBinder.pos, counterExamples)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
index 22661d6ccf..25f7224667 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
@@ -208,7 +208,7 @@ trait MatchTranslation {
case _ => (cases, None)
}
- checkMatchVariablePatterns(nonSyntheticCases)
+ if (!settings.XnoPatmatAnalysis) checkMatchVariablePatterns(nonSyntheticCases)
// we don't transform after uncurry
// (that would require more sophistication when generating trees,
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index 3fd9ce76f8..647719bf3e 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -21,9 +21,10 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
import global._
import definitions._
- final case class Suppression(exhaustive: Boolean, unreachable: Boolean)
+ final case class Suppression(suppressExhaustive: Boolean, suppressUnreachable: Boolean)
object Suppression {
val NoSuppression = Suppression(false, false)
+ val FullSuppression = Suppression(true, true)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -542,7 +543,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
debug.patmat("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
val (suppression, requireSwitch): (Suppression, Boolean) =
- if (settings.XnoPatmatAnalysis) (Suppression.NoSuppression, false)
+ if (settings.XnoPatmatAnalysis) (Suppression.FullSuppression, false)
else scrut match {
case Typed(tree, tpt) =>
val suppressExhaustive = tpt.tpe hasAnnotation UncheckedClass
@@ -574,7 +575,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
(Suppression.NoSuppression, false)
}
- emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, suppression.exhaustive).getOrElse{
+ emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, unchecked = suppression.suppressExhaustive).getOrElse{
if (requireSwitch) reporter.warning(scrut.pos, "could not emit switch for @switch annotated match")
if (casesNoSubstOnly nonEmpty) {
diff --git a/test/files/pos/patmat-suppress.flags b/test/files/pos/patmat-suppress.flags
new file mode 100644
index 0000000000..a988a5b807
--- /dev/null
+++ b/test/files/pos/patmat-suppress.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -Xno-patmat-analysis \ No newline at end of file
diff --git a/test/files/pos/patmat-suppress.scala b/test/files/pos/patmat-suppress.scala
new file mode 100644
index 0000000000..7c8aded690
--- /dev/null
+++ b/test/files/pos/patmat-suppress.scala
@@ -0,0 +1,159 @@
+// test that none of these warn due to -Xno-patmat-analysis
+// tests taken from test/files/neg/patmatexhaust.scala, test/files/neg/pat_unreachable.scala
+class TestSealedExhaustive { // compile only
+ sealed abstract class Foo
+
+ case class Bar(x:Int) extends Foo
+ case object Baz extends Foo
+
+ def ma1(x:Foo) = x match {
+ case Bar(_) => // not exhaustive
+ }
+
+ def ma2(x:Foo) = x match {
+ case Baz => // not exhaustive
+ }
+
+ sealed abstract class Mult
+ case class Kult(s:Mult) extends Mult
+ case class Qult() extends Mult
+
+ def ma33(x:Kult) = x match { // exhaustive
+ case Kult(_) => // exhaustive
+ }
+
+ def ma3(x:Mult) = (x,x) match { // not exhaustive
+ case (Kult(_), Qult()) => // Kult missing
+ //case (Kult(_), Kult(_)) =>
+ case (Qult(), Kult(_)) => // Qult missing
+ //case (Qult(), Qult()) =>
+ }
+
+ def ma3u(x:Mult) = ((x,x) : @unchecked) match { // not exhaustive, but not checked!
+ case (Kult(_), Qult()) =>
+ case (Qult(), Kult(_)) =>
+ }
+
+ sealed abstract class Deep
+
+ case object Ga extends Deep
+ sealed class Gp extends Deep
+ case object Gu extends Gp
+
+ def zma3(x:Deep) = x match { // exhaustive!
+ case _ =>
+ }
+ def zma4(x:Deep) = x match { // exhaustive!
+ case Ga =>
+ case _ =>
+ }
+
+ def ma4(x:Deep) = x match { // missing cases: Gu, Gp which is not abstract so must be included
+ case Ga =>
+ }
+
+ def ma5(x:Deep) = x match {
+ case Gu =>
+ case _ if 1 == 0 =>
+ case Ga =>
+ }
+
+ def ma6() = List(1,2) match { // give up
+ case List(1,2) =>
+ case x :: xs =>
+ }
+
+ def ma7() = List(1,2) match { //exhaustive
+ case 1::2::Nil =>
+ case _ =>
+ }
+
+ sealed class B
+ case class B1() extends B
+ case object B2 extends B
+ def ma8(x: B) = x match {
+ case _: B => true
+ }
+ def ma9(x: B) = x match {
+ case B1() => true // missing B, which is not abstract so must be included
+ case B2 => true
+ }
+
+ object ob1 {
+ sealed abstract class C
+ sealed abstract class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+
+ object ob2 {
+ sealed abstract class C
+ abstract class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 is not sealed.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+ object ob3 {
+ sealed abstract class C
+ sealed abstract class C1 extends C
+ object D1 extends C1
+ case class D2() extends C1
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 has subclasses.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+ object ob4 {
+ sealed abstract class C
+ sealed class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 is not abstract.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+}
+
+object TestUnreachable extends App {
+ def unreachable1(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x, y, z, w) => List(z,w) // redundant!
+ }
+ def unreachable2(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x, y) => List(x, y)
+ }
+
+ def not_unreachable(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x) => List(x)
+ }
+ def not_unreachable2(xs:Seq[Char]) = xs match {
+ case Seq(x, y) => x::y::Nil
+ case Seq(x, y, z, _*) => List(x,y)
+ }
+
+ def contrivedExample[A, B, C](a: A, b: B, c: C): Unit = a match {
+ case b => println("matched b")
+ case c => println("matched c")
+ case _ => println("matched neither")
+ }
+}