summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-01-27 19:01:25 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-01-29 11:10:30 +1000
commit1f4d8945f310ad803d7c165e0f53baf3c9194cf6 (patch)
treed911b6ee46c868352624f19fdf7c4b0b98bbbebe
parent79a52e6807d2797dee12bab1730765441a0e222d (diff)
downloadscala-1f4d8945f310ad803d7c165e0f53baf3c9194cf6.tar.gz
scala-1f4d8945f310ad803d7c165e0f53baf3c9194cf6.tar.bz2
scala-1f4d8945f310ad803d7c165e0f53baf3c9194cf6.zip
SI-9398 Treat case classes as one-element ADTs for analysis
Currently, exhaustivity analysis only runs for scrutinees with a sealed type. This commit treats any case class as a one-element, sealed type to enable additional analysis, such as in the new test case.
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala2
-rw-r--r--test/files/neg/t9398.check7
-rw-r--r--test/files/neg/t9398.flags1
-rw-r--r--test/files/neg/t9398/data.scala5
-rw-r--r--test/files/neg/t9398/match.scala6
-rw-r--r--test/files/pos/t5899.scala1
-rw-r--r--test/files/run/Course-2002-07.scala2
-rw-r--r--test/files/run/caseclasses.scala2
-rw-r--r--test/files/run/infix.scala1
-rw-r--r--test/files/run/patmatnew.scala4
-rw-r--r--test/files/run/t3126.scala2
-rw-r--r--test/files/run/t4124.scala8
-rw-r--r--test/files/run/t6089.scala2
-rw-r--r--test/files/run/t7459f.scala2
-rw-r--r--test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala2
15 files changed, 35 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 4286f69c96..ab3b25e76b 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -176,6 +176,8 @@ trait TreeAndTypeAnalysis extends Debugging {
filterChildren(subclasses)
})
}
+ case sym if sym.isCase =>
+ List(List(tp))
case sym =>
debug.patmat("enum unsealed "+ ((tp, sym, sym.isSealed, isPrimitiveValueClass(sym))))
diff --git a/test/files/neg/t9398.check b/test/files/neg/t9398.check
new file mode 100644
index 0000000000..f0c464daa1
--- /dev/null
+++ b/test/files/neg/t9398.check
@@ -0,0 +1,7 @@
+match.scala:3: warning: match may not be exhaustive.
+It would fail on the following input: CC(B2)
+ def test(c: CC): Unit = c match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/t9398.flags b/test/files/neg/t9398.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/t9398.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/t9398/data.scala b/test/files/neg/t9398/data.scala
new file mode 100644
index 0000000000..7a98c0e8e8
--- /dev/null
+++ b/test/files/neg/t9398/data.scala
@@ -0,0 +1,5 @@
+sealed abstract class TB
+case object B extends TB
+case object B2 extends TB
+
+case class CC(tb: TB)
diff --git a/test/files/neg/t9398/match.scala b/test/files/neg/t9398/match.scala
new file mode 100644
index 0000000000..e110c6a96a
--- /dev/null
+++ b/test/files/neg/t9398/match.scala
@@ -0,0 +1,6 @@
+class Test {
+ // Should warn that CC(B2) isn't matched
+ def test(c: CC): Unit = c match {
+ case CC(B) => ()
+ }
+}
diff --git a/test/files/pos/t5899.scala b/test/files/pos/t5899.scala
index b16f1f84fe..885baca790 100644
--- a/test/files/pos/t5899.scala
+++ b/test/files/pos/t5899.scala
@@ -14,6 +14,7 @@ trait Foo {
Bippy(Stable) match {
case Bippy(nme.WILDCARD) => 1
case Bippy(Stable) => 2 // should not be considered unreachable
+ case Bippy(_) => 3
}
}
} \ No newline at end of file
diff --git a/test/files/run/Course-2002-07.scala b/test/files/run/Course-2002-07.scala
index 2d9457653f..db6e1d8e04 100644
--- a/test/files/run/Course-2002-07.scala
+++ b/test/files/run/Course-2002-07.scala
@@ -485,7 +485,7 @@ object MB {
import Utils._;
- trait Expr {
+ sealed trait Expr {
private def count: Int = this match {
case Lit(n) => n
diff --git a/test/files/run/caseclasses.scala b/test/files/run/caseclasses.scala
index 668c984f3d..10c0916dc0 100644
--- a/test/files/run/caseclasses.scala
+++ b/test/files/run/caseclasses.scala
@@ -18,7 +18,7 @@ object M {
object Test extends App {
def Abs(x: Int) = new Abs(x * 2){}
- Abs(2) match {
+ (Abs(2): @unchecked) match {
case Abs(4) => ;
}
diff --git a/test/files/run/infix.scala b/test/files/run/infix.scala
index a867d03ce8..1d39003644 100644
--- a/test/files/run/infix.scala
+++ b/test/files/run/infix.scala
@@ -7,5 +7,6 @@ object Test extends App {
Console.println(xs)
xs match {
case null op (0, 0) op (1, 1) op (2, 2) => Console.println("OK")
+ case _ =>
}
}
diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala
index 3c0d00dc6c..2647d97836 100644
--- a/test/files/run/patmatnew.scala
+++ b/test/files/run/patmatnew.scala
@@ -539,7 +539,7 @@ object Test {
case class Operator(x: Int);
val EQ = new Operator(2);
- def analyze(x: Tuple2[Operator, Int]) = x match {
+ def analyze(x: Tuple2[Operator, Int]) = (x: @unchecked) match {
case (EQ, 0) => "0"
case (EQ, 1) => "1"
case (EQ, 2) => "2"
@@ -603,7 +603,7 @@ object Test {
object Bug1093 {
def run() {
- assert(Some(3) match {
+ assert((Some(3): @unchecked) match {
case Some(1 | 2) => false
case Some(3) => true
})
diff --git a/test/files/run/t3126.scala b/test/files/run/t3126.scala
index 36322bf896..865047ce4f 100644
--- a/test/files/run/t3126.scala
+++ b/test/files/run/t3126.scala
@@ -4,6 +4,6 @@ object Test {
def main(args: Array[String]): Unit = {
try C.unapply(null) catch { case _: MatchError => }
- try v match { case Some(1) => } catch { case _: MatchError => }
+ try ((v: @unchecked) match { case Some(1) => }) catch { case _: MatchError => }
}
}
diff --git a/test/files/run/t4124.scala b/test/files/run/t4124.scala
index 9f35b57ce3..db4e382634 100644
--- a/test/files/run/t4124.scala
+++ b/test/files/run/t4124.scala
@@ -2,22 +2,22 @@ import xml.Node
object Test extends App {
val body: Node = <elem>hi</elem>
- println ((body: AnyRef, "foo") match {
+ println (((body: AnyRef, "foo"): @unchecked) match {
case (node: Node, "bar") => "bye"
case (ser: Serializable, "foo") => "hi"
})
- println ((body, "foo") match {
+ println (((body, "foo"): @unchecked) match {
case (node: Node, "bar") => "bye"
case (ser: Serializable, "foo") => "hi"
})
- println ((body: AnyRef, "foo") match {
+ println (((body: AnyRef, "foo"): @unchecked) match {
case (node: Node, "foo") => "bye"
case (ser: Serializable, "foo") => "hi"
})
- println ((body: AnyRef, "foo") match {
+ println (((body: AnyRef, "foo"): @unchecked) match {
case (node: Node, "foo") => "bye"
case (ser: Serializable, "foo") => "hi"
})
diff --git a/test/files/run/t6089.scala b/test/files/run/t6089.scala
index c72d7ba792..c42a9f68c6 100644
--- a/test/files/run/t6089.scala
+++ b/test/files/run/t6089.scala
@@ -3,7 +3,7 @@ case class Foo(x: Int)
object Test {
def bippo(result: Boolean): Boolean = result
def bungus(m: Foo): Boolean =
- bippo(m match { case Foo(2) => bungus(m) })
+ bippo((m: @unchecked) match { case Foo(2) => bungus(m) })
def main(args: Array[String]): Unit = try {
bungus(Foo(0))
diff --git a/test/files/run/t7459f.scala b/test/files/run/t7459f.scala
index 63e2109560..5cd972129a 100644
--- a/test/files/run/t7459f.scala
+++ b/test/files/run/t7459f.scala
@@ -3,7 +3,7 @@ object Test extends App {
case class FooSeq(x: Int, y: String, z: C*)
- FooSeq(1, "a", new C()) match {
+ (FooSeq(1, "a", new C()): @unchecked) match {
case FooSeq(1, "a", x@_* ) =>
//println(x.toList)
x.asInstanceOf[x.type]
diff --git a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
index cef27b4d87..ec4621b230 100644
--- a/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
+++ b/test/junit/scala/tools/nsc/transform/patmat/PatmatBytecodeTest.scala
@@ -121,7 +121,7 @@ class PatmatBytecodeTest extends ClearAfterClass {
val code =
"""case class Foo(x: Any, y: String)
|class C {
- | def a = Foo(1, "a") match {
+ | def a = (Foo(1, "a"): @unchecked) match {
| case Foo(_: String, y) => y
| }
|}