diff options
136 files changed, 3184 insertions, 0 deletions
diff --git a/tests/patmat/NonAbstractSealed.check b/tests/patmat/NonAbstractSealed.check new file mode 100644 index 000000000..9224ee370 --- /dev/null +++ b/tests/patmat/NonAbstractSealed.check @@ -0,0 +1,5 @@ +./tests/patmat/NonAbstractSealed.scala:6: warning: match may not be exhaustive. +It would fail on the following input: _: A + (null: A) match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/NonAbstractSealed.scala b/tests/patmat/NonAbstractSealed.scala new file mode 100644 index 000000000..ff2e90aee --- /dev/null +++ b/tests/patmat/NonAbstractSealed.scala @@ -0,0 +1,10 @@ +sealed class A +class B extends A +class C extends A + +object Test { + (null: A) match { + case t: B => + case t: C => + } +} diff --git a/tests/patmat/TwoTrait.scala b/tests/patmat/TwoTrait.scala new file mode 100644 index 000000000..b8e3402c5 --- /dev/null +++ b/tests/patmat/TwoTrait.scala @@ -0,0 +1,12 @@ +object Test { + sealed trait A + sealed trait B + + abstract sealed class Parent + class Foo extends Parent with A with B + class Bar extends Parent with B with A + + (null: A) match { + case _: B => + } +} diff --git a/tests/patmat/aladdin1055/A.scala b/tests/patmat/aladdin1055/A.scala new file mode 100644 index 000000000..862336e30 --- /dev/null +++ b/tests/patmat/aladdin1055/A.scala @@ -0,0 +1,6 @@ +object A { + sealed trait T { def f: Int } + class TT extends T { def f = 0 } + + def foo = new T { def f = 1 } // local subclass of sealed trait T +} diff --git a/tests/patmat/aladdin1055/Test_1.scala.ignore b/tests/patmat/aladdin1055/Test_1.scala.ignore new file mode 100644 index 000000000..39d9b1dc9 --- /dev/null +++ b/tests/patmat/aladdin1055/Test_1.scala.ignore @@ -0,0 +1,5 @@ +object Test { + def foo(t: A.T) = t match { + case a: A.TT => 0 + } +} diff --git a/tests/patmat/aladdin1055/expected.check.ignore b/tests/patmat/aladdin1055/expected.check.ignore new file mode 100644 index 000000000..a8024ad02 --- /dev/null +++ b/tests/patmat/aladdin1055/expected.check.ignore @@ -0,0 +1,5 @@ +./tests/patmat/aladdin1055/Test_1.scala:2: warning: match may not be exhaustive. +It would fail on the following input: (_ : this.<local child>) + def foo(t: A.T) = t match { + ^ +one warning found diff --git a/tests/patmat/enum/Day.java b/tests/patmat/enum/Day.java new file mode 100644 index 000000000..eedb9a72b --- /dev/null +++ b/tests/patmat/enum/Day.java @@ -0,0 +1,4 @@ +public enum Day { + SUNDAY, MONDAY, TUESDAY, WEDNESDAY, + THURSDAY, FRIDAY, SATURDAY +}
\ No newline at end of file diff --git a/tests/patmat/enum/expected.check b/tests/patmat/enum/expected.check new file mode 100644 index 000000000..b3dafa8bd --- /dev/null +++ b/tests/patmat/enum/expected.check @@ -0,0 +1,9 @@ +./tests/patmat/enum/patmat-enum.scala:4: warning: match may not be exhaustive. +It would fail on the following input: SATURDAY, FRIDAY, THURSDAY, SUNDAY + day match { + ^ +./tests/patmat/enum/patmat-enum.scala:15: warning: match may not be exhaustive. +It would fail on the following input: SATURDAY, FRIDAY, THURSDAY + day match { + ^ +two warnings found
\ No newline at end of file diff --git a/tests/patmat/enum/patmat-enum.scala b/tests/patmat/enum/patmat-enum.scala new file mode 100644 index 000000000..ec5c90255 --- /dev/null +++ b/tests/patmat/enum/patmat-enum.scala @@ -0,0 +1,21 @@ +object Test1 { + val day: Day = ??? + + day match { + case Day.MONDAY => true + case Day.TUESDAY => true + case Day.WEDNESDAY => true + } +} + +object Test2 { + import Day._ + val day: Day = ??? + + day match { + case MONDAY => true + case TUESDAY => true + case WEDNESDAY => true + case SUNDAY => true + } +}
\ No newline at end of file diff --git a/tests/patmat/exhausting.check b/tests/patmat/exhausting.check new file mode 100644 index 000000000..790b12334 --- /dev/null +++ b/tests/patmat/exhausting.check @@ -0,0 +1,25 @@ +./tests/patmat/exhausting.scala:21: warning: match may not be exhaustive. +It would fail on the following input: List(_), List(_, _, _) + def fail1[T](xs: List[T]) = xs match { + ^ +./tests/patmat/exhausting.scala:27: warning: match may not be exhaustive. +It would fail on the following input: Nil + def fail2[T](xs: List[T]) = xs match { + ^ +./tests/patmat/exhausting.scala:32: warning: match may not be exhaustive. +It would fail on the following input: List(_, _) + def fail3a(xs: List[Int]) = xs match { + ^ +./tests/patmat/exhausting.scala:39: warning: match may not be exhaustive. +It would fail on the following input: Bar3 + def fail3[T](x: Foo[T]) = x match { + ^ +./tests/patmat/exhausting.scala:44: warning: match may not be exhaustive. +It would fail on the following input: (Bar2, Bar2) + def fail4[T <: AnyRef](xx: (Foo[T], Foo[T])) = xx match { + ^ +./tests/patmat/exhausting.scala:53: warning: match may not be exhaustive. +It would fail on the following input: (Bar2, Bar2), (Bar2, Bar1), (Bar1, Bar3), (Bar1, Bar2) + def fail5[T](xx: (Foo[T], Foo[T])) = xx match { + ^ +6 warnings found diff --git a/tests/patmat/exhausting.scala b/tests/patmat/exhausting.scala new file mode 100644 index 000000000..03e8198dd --- /dev/null +++ b/tests/patmat/exhausting.scala @@ -0,0 +1,58 @@ +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[_]) => () + } + + // fails for: ::(_, Nil), ::(_, ::(_, ::(_, _))), ... + def fail1[T](xs: List[T]) = xs match { + case Nil => "ok" + case x :: y :: Nil => "ok" + } + + // fails for: Nil + def fail2[T](xs: List[T]) = xs match { + case _ :: _ => "ok" + } + + // fails for: ::(<not in (2, 1)>, _) + def fail3a(xs: List[Int]) = xs match { + case 1 :: _ => + case 2 :: _ => + case Nil => + } + + // fails for: Bar3 + def fail3[T](x: Foo[T]) = x match { + case Bar1 => "ok" + case Bar2 => "ok" + } + // fails for: (Bar2, Bar2) + def fail4[T <: AnyRef](xx: (Foo[T], Foo[T])) = xx match { + case (Bar1, Bar1) => () + case (Bar2, Bar3) => () + case (Bar3, _) => () + } + // fails for: (Bar1, Bar2) + // fails for: (Bar1, Bar3) + // fails for: (Bar2, Bar1) + // fails for: (Bar2, Bar2) + def fail5[T](xx: (Foo[T], Foo[T])) = xx match { + case (Bar1, Bar1) => () + case (Bar2, Bar3) => () + case (Bar3, _) => () + } +} diff --git a/tests/patmat/exhaustive_heuristics.scala b/tests/patmat/exhaustive_heuristics.scala new file mode 100644 index 000000000..7d682f6aa --- /dev/null +++ b/tests/patmat/exhaustive_heuristics.scala @@ -0,0 +1,26 @@ +// tests exhaustivity doesn't give warnings (due to its heuristic rewrites kicking in or it backing off) +object Test { + // List() => Nil + List(1) match { + case List() => + case x :: xs => + } + + // we don't look into guards + val turnOffChecks = true + List(1) match { + case _ if turnOffChecks => + } + + // we back off when there are any user-defined extractors + // in fact this is exhaustive, but we pretend we don't know since List's unapplySeq is not special to the compiler + // to compensate our ignorance, we back off + // well, in truth, we do rewrite List() to Nil, but otherwise we do nothing + // the full rewrite List(a, b) to a :: b :: Nil, for example is planned (but not sure it's a good idea) + List(true, false) match { + case List(_, _, _:_*) => + case List(node, _:_*) => + case Nil => + } + +}
\ No newline at end of file diff --git a/tests/patmat/for.scala b/tests/patmat/for.scala new file mode 100644 index 000000000..ae9dcf65e --- /dev/null +++ b/tests/patmat/for.scala @@ -0,0 +1,5 @@ +object Test { + def foo[A, B](l: List[(A, B)]): List[A] = { + for ((a, b) <- l) yield a + } +}
\ No newline at end of file diff --git a/tests/patmat/gadt.check b/tests/patmat/gadt.check new file mode 100644 index 000000000..f2154fa60 --- /dev/null +++ b/tests/patmat/gadt.check @@ -0,0 +1,17 @@ +./tests/patmat/gadt.scala:13: warning: match may not be exhaustive. +It would fail on the following input: IntLit(_) + def foo1b(x: Expr[Int]) = x match { + ^ +./tests/patmat/gadt.scala:22: warning: match may not be exhaustive. +It would fail on the following input: Or(_, _) + def foo2b(x: Expr[Boolean]) = x match { + ^ +./tests/patmat/gadt.scala:45: warning: match may not be exhaustive. +It would fail on the following input: BooleanLit(_), IntLit(_) + def foo4b(x: Expr[_]) = x match { + ^ +./tests/patmat/gadt.scala:55: warning: match may not be exhaustive. +It would fail on the following input: Sum(_, _) + def foo5b[T <: Int](x: Expr[T]) = x match { + ^ +four warnings found
\ No newline at end of file diff --git a/tests/patmat/gadt.scala b/tests/patmat/gadt.scala new file mode 100644 index 000000000..0541ed61f --- /dev/null +++ b/tests/patmat/gadt.scala @@ -0,0 +1,58 @@ +object Test { + sealed trait Expr[T] + case class IntLit(i: Int) extends Expr[Int] + case class BooleanLit(b: Boolean) extends Expr[Boolean] + case class Sum(l: Expr[Int], r: Expr[Int]) extends Expr[Int] + case class Or(l: Expr[Boolean], r: Expr[Boolean]) extends Expr[Boolean] + + def foo1a(x: Expr[Int]) = x match { + case _: IntLit => true + case _: Sum => true + } + + def foo1b(x: Expr[Int]) = x match { + case _: Sum => true + } + + def foo2a(x: Expr[Boolean]) = x match { + case _: BooleanLit => true + case _: Or => true + } + + def foo2b(x: Expr[Boolean]) = x match { + case _: BooleanLit => true + } + + def foo3a(x: Expr[Boolean]) = x match { + case _: BooleanLit => true + case _: Or => true + // case _: Sum => true + } + + def foo3b(x: Expr[Int]) = x match { + case _: IntLit => true + case _: Sum => true + // case _: Or => true + } + + def foo4a(x: Expr[_]) = x match { + case _: IntLit => true + case _: Sum => true + case _: BooleanLit => true + case _: Or => true + } + + def foo4b(x: Expr[_]) = x match { + case _: Sum => true + case _: Or => true + } + + def foo5a[T <: Int](x: Expr[T]) = x match { + case _: IntLit => true + case _: Sum => true + } + + def foo5b[T <: Int](x: Expr[T]) = x match { + case _: IntLit => true + } +} diff --git a/tests/patmat/gadt2.scala.ignore b/tests/patmat/gadt2.scala.ignore new file mode 100644 index 000000000..80ba72c70 --- /dev/null +++ b/tests/patmat/gadt2.scala.ignore @@ -0,0 +1,14 @@ +sealed trait Nat[+T] +case class Zero() extends Nat[Nothing] +case class Succ[T]() extends Nat[T] + +sealed trait Vect[+N <: Nat[_], +T] +case class VN[T]() extends Vect[Zero, T] +case class VC[T, N <: Nat[_]](x: T, xs: Vect[N, T]) extends Vect[Succ[N], T] + +object Test { + def foo[N <: Nat[_], A, B](v1: Vect[N, A], v2: Vect[N, B]) = (v1, v2) match { + case (VN(), VN()) => 1 + case (VC(x, xs), VC(y, ys)) => 2 + } +} diff --git a/tests/patmat/gadt3.scala.ignore b/tests/patmat/gadt3.scala.ignore new file mode 100644 index 000000000..c39416414 --- /dev/null +++ b/tests/patmat/gadt3.scala.ignore @@ -0,0 +1,10 @@ +sealed trait Expr[T] +case class IntExpr(x: Int) extends Expr[Int] +case class BooleanExpr(b: Boolean) extends Expr[Boolean] + +object Test { + def foo[T](x: Expr[T], y: Expr[T]) = (x, y) match { + case (IntExpr(_), IntExpr(_)) => + case (BooleanExpr(_), BooleanExpr(_)) => + } +}
\ No newline at end of file diff --git a/tests/patmat/i947.check b/tests/patmat/i947.check new file mode 100644 index 000000000..5cce559c4 --- /dev/null +++ b/tests/patmat/i947.check @@ -0,0 +1,4 @@ +./tests/patmat/i947.scala:10: warning: unreachable code + case ys: List[d18383] => false + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/i947.scala b/tests/patmat/i947.scala new file mode 100644 index 000000000..0f2d9e775 --- /dev/null +++ b/tests/patmat/i947.scala @@ -0,0 +1,16 @@ +object Test { + + class c { + + private var x: Int = 0 + + override def equals(other: Any) = other match { + case o: c => x == o.x + case xs: List[c] => false + case ys: List[d18383] => false + case _ => false + } + + + } +} diff --git a/tests/patmat/outer-ref-checks.scala b/tests/patmat/outer-ref-checks.scala new file mode 100644 index 000000000..35983fe92 --- /dev/null +++ b/tests/patmat/outer-ref-checks.scala @@ -0,0 +1,106 @@ +import scala.annotation.unchecked.uncheckedVariance + +class Outer { + // A final class gets no outer ref, so we expect to see warnings where an outer ref check should be performed + final case class Inner(val s: String) // unchecked warning + + def belongs(a: Any): Unit = a match { + case Inner(s) => // unchecked warning + case _ => + } + + def belongsStaticSameOuter(a: Inner): Unit = a match { + case Inner(s) => // no need for outer check + // match is exhaustive, no default case needed + } + + def belongsOtherOuter(a: Outer#Inner): Unit = a match { + case Inner(s) => // unchecked warning + case O.Inner(s) => // unchecked warning + case _ => + } +} + +object O extends Outer { + def belongsStaticSameOuter2(a: Inner): Unit = a match { + case Inner(s) => // no need for outer check + // match is exhaustive, no default case needed + } + + def belongsStaticSameOuter3(a: Inner): Unit = a match { + case _: Inner => // no need for outer check + // match is exhaustive, no default case needed + } + + def belongsStaticSameOuter4(a: Inner): Unit = a match { + case _: (Inner @uncheckedVariance) => // no need for outer check + // match is exhaustive, no default case needed + } + + def belongsOtherOuter2(a: Outer#Inner): Unit = a match { + case Inner(s) => // unchecked warning + case _ => + } + + def belongsOtherOuter3(a: Outer#Inner): Unit = a match { + case _: Inner => // unchecked warning + case _ => + } + + def belongsOtherOuter4(a: Outer#Inner): Unit = a match { + case _: (Inner @unchecked) => // warning supressed + case _ => + } + + def belongsOtherOuter5(a: Outer#Inner): Unit = a match { + case _: (Inner @uncheckedVariance) => // unchecked warning + case _ => + } + + def nested: Unit = { + final case class I(s: String) + + def check1(a: Any): Unit = a match { + case I(s) => // no need for outer check + case _ => + } + + def check2(a: I): Unit = a match { + case I(s) => // no need for outer check + // match is exhaustive, no default case needed + } + } +} + +class O2 { + def nested: Unit = { + final case class I(s: String) + + def check1(a: Any): Unit = a match { + case I(s) => // no need for outer check (is this correct?) + case _ => + } + + def check2(a: I): Unit = a match { + case I(s) => // no need for outer check (is this correct?) + // match is exhaustive, no default case needed + } + } +} + +package p { + object T { + case class C(x: Int) + } +} + +object U { + val T = p.T +} + +class Test { + def m(a: Any) = a match { + case U.T.C(1) => 1 // used to warn + case _ => 1 + } +} diff --git a/tests/patmat/partial-function.scala b/tests/patmat/partial-function.scala new file mode 100644 index 000000000..f168489da --- /dev/null +++ b/tests/patmat/partial-function.scala @@ -0,0 +1,12 @@ +sealed abstract class TA +sealed abstract class TB extends TA +case object B extends TB +case object B2 extends TB + +case class CC(i: Int, tb: TB) + +object Test { + def foo: PartialFunction[CC, Unit] = { + case CC(_, B) => () + } +}
\ No newline at end of file diff --git a/tests/patmat/patmat-adt.check b/tests/patmat/patmat-adt.check new file mode 100644 index 000000000..f4e1ce369 --- /dev/null +++ b/tests/patmat/patmat-adt.check @@ -0,0 +1,21 @@ +./tests/patmat/patmat-adt.scala:7: warning: match may not be exhaustive. +It would fail on the following input: Bad(Good(_)), Good(Bad(_)) + def foo1a(x: Odd) = x match { // warning: Good(_: Bad), Bad(_: Good) + ^ +./tests/patmat/patmat-adt.scala:19: warning: match may not be exhaustive. +It would fail on the following input: Some(_) + def foo2(x: Option[Int]) = x match { // warning: Some(_: Int) + ^ +./tests/patmat/patmat-adt.scala:24: warning: match may not be exhaustive. +It would fail on the following input: (None, Some(_)), (_, Some(_)) + def foo3a[T](x: Option[T]) = (x, x) match { // warning: (Some(_), Some(_)), (None, Some(_)) + ^ +./tests/patmat/patmat-adt.scala:29: warning: match may not be exhaustive. +It would fail on the following input: (None, None), (Some(_), Some(_)) + def foo3b[T](x: Option[T]) = (x, x) match { // warning: (Some(_), Some(_)), (None, None) + ^ +./tests/patmat/patmat-adt.scala:50: warning: match may not be exhaustive. +It would fail on the following input: LetL(BooleanLit), LetL(IntLit) + def foo5(tree: Tree) : Any = tree match { + ^ +5 warnings found
\ No newline at end of file diff --git a/tests/patmat/patmat-adt.scala b/tests/patmat/patmat-adt.scala new file mode 100644 index 000000000..e7eac4e4a --- /dev/null +++ b/tests/patmat/patmat-adt.scala @@ -0,0 +1,58 @@ +object PatmatADT { + abstract sealed class Odd(x: Odd) + + case class Good(x: Odd) extends Odd(x) + case class Bad(x: Odd) extends Odd(x) + + def foo1a(x: Odd) = x match { // warning: Good(_: Bad), Bad(_: Good) + case Good(_: Good) => false + case Bad(_: Bad) => false + } + + def foo1b(x: Odd) = x match { + case Good(_: Good) => false + case Bad(_: Bad) => false + case Good(_: Bad) => false + case Bad(_: Good) => false + } + + def foo2(x: Option[Int]) = x match { // warning: Some(_: Int) + case Some(_: Double) => true + case None => true + } + + def foo3a[T](x: Option[T]) = (x, x) match { // warning: (Some(_), Some(_)), (None, Some(_)) + case (Some(_), None) => true + case (None, None) => true + } + + def foo3b[T](x: Option[T]) = (x, x) match { // warning: (Some(_), Some(_)), (None, None) + case (Some(_), None) => true + case (None, Some(_)) => true + } + + sealed trait Base + case class Foo() extends Base + + def foo4(x: Base) = x match { + case Foo() => + } + + sealed abstract class CL3Literal + case object IntLit extends CL3Literal + case object CharLit extends CL3Literal + case object BooleanLit extends CL3Literal + + + sealed abstract class Tree + case class LetL(value: CL3Literal) extends Tree + + def foo5(tree: Tree) : Any = tree match { + case LetL(CharLit) => + } + + def foo6[T](l: List[T]): Boolean = l match { + case x::xs => true + case Nil => false + } +}
\ No newline at end of file diff --git a/tests/patmat/patmat-extractor.scala b/tests/patmat/patmat-extractor.scala new file mode 100644 index 000000000..02fde96dc --- /dev/null +++ b/tests/patmat/patmat-extractor.scala @@ -0,0 +1,17 @@ +sealed trait Node +case class NodeA(i: Int) extends Node +case class NodeB(b: Boolean) extends Node +case class NodeC(s: String) extends Node + +object Node { + def unapply(node: Node): Option[(Node, Node)] = ??? +} + +// currently scalac can't do anything with following +// it's possible to do better in our case +object Test { + def foo(x: Node): Boolean = x match { // unexhaustive + case Node(NodeA(_), NodeB(_)) => true + case Node(NodeA(4), NodeB(false)) => true // unreachable code + } +}
\ No newline at end of file diff --git a/tests/patmat/patmat-indent.check b/tests/patmat/patmat-indent.check new file mode 100644 index 000000000..3a76e0a95 --- /dev/null +++ b/tests/patmat/patmat-indent.check @@ -0,0 +1,13 @@ +./tests/patmat/patmat-indent.scala:9: warning: match may not be exhaustive. +It would fail on the following input: Nil + def foo1a[T](l: List[T]) = l match { + ^ +./tests/patmat/patmat-indent.scala:23: warning: match may not be exhaustive. +It would fail on the following input: _: Boolean + def foo2(b: Boolean) = b match { + ^ +./tests/patmat/patmat-indent.scala:27: warning: match may not be exhaustive. +It would fail on the following input: _: Int + def foo3(x: Int) = x match { + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/patmat-indent.scala b/tests/patmat/patmat-indent.scala new file mode 100644 index 000000000..ef25bb2c7 --- /dev/null +++ b/tests/patmat/patmat-indent.scala @@ -0,0 +1,30 @@ +object Test { + val Nil = scala.Nil + val X = 5 + + object Inner { + val Y = false + } + + def foo1a[T](l: List[T]) = l match { + case x::xs => false + } + + def foo1b[T](l: List[T]) = l match { + case Nil => true + case x::xs => false + } + + def foo1c[T](l: List[T]) = l match { + case Test.Nil => true + case x::xs => false + } + + def foo2(b: Boolean) = b match { + case Inner.Y => false + } + + def foo3(x: Int) = x match { + case X => 0 + } +}
\ No newline at end of file diff --git a/tests/patmat/patmat-ortype.check b/tests/patmat/patmat-ortype.check new file mode 100644 index 000000000..2291da251 --- /dev/null +++ b/tests/patmat/patmat-ortype.check @@ -0,0 +1,13 @@ +./tests/patmat/patmat-ortype.scala:8: warning: match may not be exhaustive. +It would fail on the following input: _: String + def foo2a(x: Int | Double | String) = x match { // _: String not matched + ^ +./tests/patmat/patmat-ortype.scala:18: warning: match may not be exhaustive. +It would fail on the following input: Some(_: String), None + def foo3(x: Option[Int | Double | String]) = x match { // warning: None, Some(_: String) not matched + ^ +./tests/patmat/patmat-ortype.scala:36: warning: match may not be exhaustive. +It would fail on the following input: Some(_: String) + def foo5b(x: Option[Int | Double | String]) = x match { // warning: Some(_: String) not matched + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/patmat-ortype.scala b/tests/patmat/patmat-ortype.scala new file mode 100644 index 000000000..c7419acd3 --- /dev/null +++ b/tests/patmat/patmat-ortype.scala @@ -0,0 +1,40 @@ +object PatmatOrType { + + def foo1(x: Int | Double) = x match { + case _: Int => true + case _: Double => true + } + + def foo2a(x: Int | Double | String) = x match { // _: String not matched + case _: Int => true + case _: Double => true + } + + def foo2b(x: Int | Double | String) = x match { + case _: Int => true + case _: (Double | String) => true + } + + def foo3(x: Option[Int | Double | String]) = x match { // warning: None, Some(_: String) not matched + case Some(_: Int) => true + case Some(_: Double) => true + } + + def foo4(x: Option[Int | Double | String]) = x match { + case Some(_: Int) => true + case Some(_: Double) => true + case Some(_: String) => true + case None => false + } + + def foo5a(x: Option[Int | Double | String]) = x match { + case Some(_: (Int | Double)) => true + case Some(_: String) => true + case None => false + } + + def foo5b(x: Option[Int | Double | String]) = x match { // warning: Some(_: String) not matched + case Some(_: (Int | Double)) => true + case None => false + } +}
\ No newline at end of file diff --git a/tests/patmat/patmatexhaust-huge.check b/tests/patmat/patmatexhaust-huge.check new file mode 100644 index 000000000..06cac90bd --- /dev/null +++ b/tests/patmat/patmatexhaust-huge.check @@ -0,0 +1,5 @@ +./tests/patmat/patmatexhaust-huge.scala:404: warning: match may not be exhaustive. +It would fail on the following input: C397, C392 + def f(c: C): Int = c match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/patmatexhaust-huge.scala b/tests/patmat/patmatexhaust-huge.scala new file mode 100644 index 000000000..c4008b995 --- /dev/null +++ b/tests/patmat/patmatexhaust-huge.scala @@ -0,0 +1,806 @@ +abstract sealed trait C +case object C1 extends C +case object C2 extends C +case object C3 extends C +case object C4 extends C +case object C5 extends C +case object C6 extends C +case object C7 extends C +case object C8 extends C +case object C9 extends C +case object C10 extends C +case object C11 extends C +case object C12 extends C +case object C13 extends C +case object C14 extends C +case object C15 extends C +case object C16 extends C +case object C17 extends C +case object C18 extends C +case object C19 extends C +case object C20 extends C +case object C21 extends C +case object C22 extends C +case object C23 extends C +case object C24 extends C +case object C25 extends C +case object C26 extends C +case object C27 extends C +case object C28 extends C +case object C29 extends C +case object C30 extends C +case object C31 extends C +case object C32 extends C +case object C33 extends C +case object C34 extends C +case object C35 extends C +case object C36 extends C +case object C37 extends C +case object C38 extends C +case object C39 extends C +case object C40 extends C +case object C41 extends C +case object C42 extends C +case object C43 extends C +case object C44 extends C +case object C45 extends C +case object C46 extends C +case object C47 extends C +case object C48 extends C +case object C49 extends C +case object C50 extends C +case object C51 extends C +case object C52 extends C +case object C53 extends C +case object C54 extends C +case object C55 extends C +case object C56 extends C +case object C57 extends C +case object C58 extends C +case object C59 extends C +case object C60 extends C +case object C61 extends C +case object C62 extends C +case object C63 extends C +case object C64 extends C +case object C65 extends C +case object C66 extends C +case object C67 extends C +case object C68 extends C +case object C69 extends C +case object C70 extends C +case object C71 extends C +case object C72 extends C +case object C73 extends C +case object C74 extends C +case object C75 extends C +case object C76 extends C +case object C77 extends C +case object C78 extends C +case object C79 extends C +case object C80 extends C +case object C81 extends C +case object C82 extends C +case object C83 extends C +case object C84 extends C +case object C85 extends C +case object C86 extends C +case object C87 extends C +case object C88 extends C +case object C89 extends C +case object C90 extends C +case object C91 extends C +case object C92 extends C +case object C93 extends C +case object C94 extends C +case object C95 extends C +case object C96 extends C +case object C97 extends C +case object C98 extends C +case object C99 extends C +case object C100 extends C +case object C101 extends C +case object C102 extends C +case object C103 extends C +case object C104 extends C +case object C105 extends C +case object C106 extends C +case object C107 extends C +case object C108 extends C +case object C109 extends C +case object C110 extends C +case object C111 extends C +case object C112 extends C +case object C113 extends C +case object C114 extends C +case object C115 extends C +case object C116 extends C +case object C117 extends C +case object C118 extends C +case object C119 extends C +case object C120 extends C +case object C121 extends C +case object C122 extends C +case object C123 extends C +case object C124 extends C +case object C125 extends C +case object C126 extends C +case object C127 extends C +case object C128 extends C +case object C129 extends C +case object C130 extends C +case object C131 extends C +case object C132 extends C +case object C133 extends C +case object C134 extends C +case object C135 extends C +case object C136 extends C +case object C137 extends C +case object C138 extends C +case object C139 extends C +case object C140 extends C +case object C141 extends C +case object C142 extends C +case object C143 extends C +case object C144 extends C +case object C145 extends C +case object C146 extends C +case object C147 extends C +case object C148 extends C +case object C149 extends C +case object C150 extends C +case object C151 extends C +case object C152 extends C +case object C153 extends C +case object C154 extends C +case object C155 extends C +case object C156 extends C +case object C157 extends C +case object C158 extends C +case object C159 extends C +case object C160 extends C +case object C161 extends C +case object C162 extends C +case object C163 extends C +case object C164 extends C +case object C165 extends C +case object C166 extends C +case object C167 extends C +case object C168 extends C +case object C169 extends C +case object C170 extends C +case object C171 extends C +case object C172 extends C +case object C173 extends C +case object C174 extends C +case object C175 extends C +case object C176 extends C +case object C177 extends C +case object C178 extends C +case object C179 extends C +case object C180 extends C +case object C181 extends C +case object C182 extends C +case object C183 extends C +case object C184 extends C +case object C185 extends C +case object C186 extends C +case object C187 extends C +case object C188 extends C +case object C189 extends C +case object C190 extends C +case object C191 extends C +case object C192 extends C +case object C193 extends C +case object C194 extends C +case object C195 extends C +case object C196 extends C +case object C197 extends C +case object C198 extends C +case object C199 extends C +case object C200 extends C +case object C201 extends C +case object C202 extends C +case object C203 extends C +case object C204 extends C +case object C205 extends C +case object C206 extends C +case object C207 extends C +case object C208 extends C +case object C209 extends C +case object C210 extends C +case object C211 extends C +case object C212 extends C +case object C213 extends C +case object C214 extends C +case object C215 extends C +case object C216 extends C +case object C217 extends C +case object C218 extends C +case object C219 extends C +case object C220 extends C +case object C221 extends C +case object C222 extends C +case object C223 extends C +case object C224 extends C +case object C225 extends C +case object C226 extends C +case object C227 extends C +case object C228 extends C +case object C229 extends C +case object C230 extends C +case object C231 extends C +case object C232 extends C +case object C233 extends C +case object C234 extends C +case object C235 extends C +case object C236 extends C +case object C237 extends C +case object C238 extends C +case object C239 extends C +case object C240 extends C +case object C241 extends C +case object C242 extends C +case object C243 extends C +case object C244 extends C +case object C245 extends C +case object C246 extends C +case object C247 extends C +case object C248 extends C +case object C249 extends C +case object C250 extends C +case object C251 extends C +case object C252 extends C +case object C253 extends C +case object C254 extends C +case object C255 extends C +case object C256 extends C +case object C257 extends C +case object C258 extends C +case object C259 extends C +case object C260 extends C +case object C261 extends C +case object C262 extends C +case object C263 extends C +case object C264 extends C +case object C265 extends C +case object C266 extends C +case object C267 extends C +case object C268 extends C +case object C269 extends C +case object C270 extends C +case object C271 extends C +case object C272 extends C +case object C273 extends C +case object C274 extends C +case object C275 extends C +case object C276 extends C +case object C277 extends C +case object C278 extends C +case object C279 extends C +case object C280 extends C +case object C281 extends C +case object C282 extends C +case object C283 extends C +case object C284 extends C +case object C285 extends C +case object C286 extends C +case object C287 extends C +case object C288 extends C +case object C289 extends C +case object C290 extends C +case object C291 extends C +case object C292 extends C +case object C293 extends C +case object C294 extends C +case object C295 extends C +case object C296 extends C +case object C297 extends C +case object C298 extends C +case object C299 extends C +case object C300 extends C +case object C301 extends C +case object C302 extends C +case object C303 extends C +case object C304 extends C +case object C305 extends C +case object C306 extends C +case object C307 extends C +case object C308 extends C +case object C309 extends C +case object C310 extends C +case object C311 extends C +case object C312 extends C +case object C313 extends C +case object C314 extends C +case object C315 extends C +case object C316 extends C +case object C317 extends C +case object C318 extends C +case object C319 extends C +case object C320 extends C +case object C321 extends C +case object C322 extends C +case object C323 extends C +case object C324 extends C +case object C325 extends C +case object C326 extends C +case object C327 extends C +case object C328 extends C +case object C329 extends C +case object C330 extends C +case object C331 extends C +case object C332 extends C +case object C333 extends C +case object C334 extends C +case object C335 extends C +case object C336 extends C +case object C337 extends C +case object C338 extends C +case object C339 extends C +case object C340 extends C +case object C341 extends C +case object C342 extends C +case object C343 extends C +case object C344 extends C +case object C345 extends C +case object C346 extends C +case object C347 extends C +case object C348 extends C +case object C349 extends C +case object C350 extends C +case object C351 extends C +case object C352 extends C +case object C353 extends C +case object C354 extends C +case object C355 extends C +case object C356 extends C +case object C357 extends C +case object C358 extends C +case object C359 extends C +case object C360 extends C +case object C361 extends C +case object C362 extends C +case object C363 extends C +case object C364 extends C +case object C365 extends C +case object C366 extends C +case object C367 extends C +case object C368 extends C +case object C369 extends C +case object C370 extends C +case object C371 extends C +case object C372 extends C +case object C373 extends C +case object C374 extends C +case object C375 extends C +case object C376 extends C +case object C377 extends C +case object C378 extends C +case object C379 extends C +case object C380 extends C +case object C381 extends C +case object C382 extends C +case object C383 extends C +case object C384 extends C +case object C385 extends C +case object C386 extends C +case object C387 extends C +case object C388 extends C +case object C389 extends C +case object C390 extends C +case object C391 extends C +case object C392 extends C +case object C393 extends C +case object C394 extends C +case object C395 extends C +case object C396 extends C +case object C397 extends C +case object C398 extends C +case object C399 extends C +case object C400 extends C + +object M { + def f(c: C): Int = c match { + case C1 => 1 + case C2 => 2 + case C3 => 3 + case C4 => 4 + case C5 => 5 + case C6 => 6 + case C7 => 7 + case C8 => 8 + case C9 => 9 + case C10 => 10 + case C11 => 11 + case C12 => 12 + case C13 => 13 + case C14 => 14 + case C15 => 15 + case C16 => 16 + case C17 => 17 + case C18 => 18 + case C19 => 19 + case C20 => 20 + case C21 => 21 + case C22 => 22 + case C23 => 23 + case C24 => 24 + case C25 => 25 + case C26 => 26 + case C27 => 27 + case C28 => 28 + case C29 => 29 + case C30 => 30 + case C31 => 31 + case C32 => 32 + case C33 => 33 + case C34 => 34 + case C35 => 35 + case C36 => 36 + case C37 => 37 + case C38 => 38 + case C39 => 39 + case C40 => 40 + case C41 => 41 + case C42 => 42 + case C43 => 43 + case C44 => 44 + case C45 => 45 + case C46 => 46 + case C47 => 47 + case C48 => 48 + case C49 => 49 + case C50 => 50 + case C51 => 51 + case C52 => 52 + case C53 => 53 + case C54 => 54 + case C55 => 55 + case C56 => 56 + case C57 => 57 + case C58 => 58 + case C59 => 59 + case C60 => 60 + case C61 => 61 + case C62 => 62 + case C63 => 63 + case C64 => 64 + case C65 => 65 + case C66 => 66 + case C67 => 67 + case C68 => 68 + case C69 => 69 + case C70 => 70 + case C71 => 71 + case C72 => 72 + case C73 => 73 + case C74 => 74 + case C75 => 75 + case C76 => 76 + case C77 => 77 + case C78 => 78 + case C79 => 79 + case C80 => 80 + case C81 => 81 + case C82 => 82 + case C83 => 83 + case C84 => 84 + case C85 => 85 + case C86 => 86 + case C87 => 87 + case C88 => 88 + case C89 => 89 + case C90 => 90 + case C91 => 91 + case C92 => 92 + case C93 => 93 + case C94 => 94 + case C95 => 95 + case C96 => 96 + case C97 => 97 + case C98 => 98 + case C99 => 99 + case C100 => 100 + case C101 => 101 + case C102 => 102 + case C103 => 103 + case C104 => 104 + case C105 => 105 + case C106 => 106 + case C107 => 107 + case C108 => 108 + case C109 => 109 + case C110 => 110 + case C111 => 111 + case C112 => 112 + case C113 => 113 + case C114 => 114 + case C115 => 115 + case C116 => 116 + case C117 => 117 + case C118 => 118 + case C119 => 119 + case C120 => 120 + case C121 => 121 + case C122 => 122 + case C123 => 123 + case C124 => 124 + case C125 => 125 + case C126 => 126 + case C127 => 127 + case C128 => 128 + case C129 => 129 + case C130 => 130 + case C131 => 131 + case C132 => 132 + case C133 => 133 + case C134 => 134 + case C135 => 135 + case C136 => 136 + case C137 => 137 + case C138 => 138 + case C139 => 139 + case C140 => 140 + case C141 => 141 + case C142 => 142 + case C143 => 143 + case C144 => 144 + case C145 => 145 + case C146 => 146 + case C147 => 147 + case C148 => 148 + case C149 => 149 + case C150 => 150 + case C151 => 151 + case C152 => 152 + case C153 => 153 + case C154 => 154 + case C155 => 155 + case C156 => 156 + case C157 => 157 + case C158 => 158 + case C159 => 159 + case C160 => 160 + case C161 => 161 + case C162 => 162 + case C163 => 163 + case C164 => 164 + case C165 => 165 + case C166 => 166 + case C167 => 167 + case C168 => 168 + case C169 => 169 + case C170 => 170 + case C171 => 171 + case C172 => 172 + case C173 => 173 + case C174 => 174 + case C175 => 175 + case C176 => 176 + case C177 => 177 + case C178 => 178 + case C179 => 179 + case C180 => 180 + case C181 => 181 + case C182 => 182 + case C183 => 183 + case C184 => 184 + case C185 => 185 + case C186 => 186 + case C187 => 187 + case C188 => 188 + case C189 => 189 + case C190 => 190 + case C191 => 191 + case C192 => 192 + case C193 => 193 + case C194 => 194 + case C195 => 195 + case C196 => 196 + case C197 => 197 + case C198 => 198 + case C199 => 199 + case C200 => 200 + case C201 => 201 + case C202 => 202 + case C203 => 203 + case C204 => 204 + case C205 => 205 + case C206 => 206 + case C207 => 207 + case C208 => 208 + case C209 => 209 + case C210 => 210 + case C211 => 211 + case C212 => 212 + case C213 => 213 + case C214 => 214 + case C215 => 215 + case C216 => 216 + case C217 => 217 + case C218 => 218 + case C219 => 219 + case C220 => 220 + case C221 => 221 + case C222 => 222 + case C223 => 223 + case C224 => 224 + case C225 => 225 + case C226 => 226 + case C227 => 227 + case C228 => 228 + case C229 => 229 + case C230 => 230 + case C231 => 231 + case C232 => 232 + case C233 => 233 + case C234 => 234 + case C235 => 235 + case C236 => 236 + case C237 => 237 + case C238 => 238 + case C239 => 239 + case C240 => 240 + case C241 => 241 + case C242 => 242 + case C243 => 243 + case C244 => 244 + case C245 => 245 + case C246 => 246 + case C247 => 247 + case C248 => 248 + case C249 => 249 + case C250 => 250 + case C251 => 251 + case C252 => 252 + case C253 => 253 + case C254 => 254 + case C255 => 255 + case C256 => 256 + case C257 => 257 + case C258 => 258 + case C259 => 259 + case C260 => 260 + case C261 => 261 + case C262 => 262 + case C263 => 263 + case C264 => 264 + case C265 => 265 + case C266 => 266 + case C267 => 267 + case C268 => 268 + case C269 => 269 + case C270 => 270 + case C271 => 271 + case C272 => 272 + case C273 => 273 + case C274 => 274 + case C275 => 275 + case C276 => 276 + case C277 => 277 + case C278 => 278 + case C279 => 279 + case C280 => 280 + case C281 => 281 + case C282 => 282 + case C283 => 283 + case C284 => 284 + case C285 => 285 + case C286 => 286 + case C287 => 287 + case C288 => 288 + case C289 => 289 + case C290 => 290 + case C291 => 291 + case C292 => 292 + case C293 => 293 + case C294 => 294 + case C295 => 295 + case C296 => 296 + case C297 => 297 + case C298 => 298 + case C299 => 299 + case C300 => 300 + case C301 => 301 + case C302 => 302 + case C303 => 303 + case C304 => 304 + case C305 => 305 + case C306 => 306 + case C307 => 307 + case C308 => 308 + case C309 => 309 + case C310 => 310 + case C311 => 311 + case C312 => 312 + case C313 => 313 + case C314 => 314 + case C315 => 315 + case C316 => 316 + case C317 => 317 + case C318 => 318 + case C319 => 319 + case C320 => 320 + case C321 => 321 + case C322 => 322 + case C323 => 323 + case C324 => 324 + case C325 => 325 + case C326 => 326 + case C327 => 327 + case C328 => 328 + case C329 => 329 + case C330 => 330 + case C331 => 331 + case C332 => 332 + case C333 => 333 + case C334 => 334 + case C335 => 335 + case C336 => 336 + case C337 => 337 + case C338 => 338 + case C339 => 339 + case C340 => 340 + case C341 => 341 + case C342 => 342 + case C343 => 343 + case C344 => 344 + case C345 => 345 + case C346 => 346 + case C347 => 347 + case C348 => 348 + case C349 => 349 + case C350 => 350 + case C351 => 351 + case C352 => 352 + case C353 => 353 + case C354 => 354 + case C355 => 355 + case C356 => 356 + case C357 => 357 + case C358 => 358 + case C359 => 359 + case C360 => 360 + case C361 => 361 + case C362 => 362 + case C363 => 363 + case C364 => 364 + case C365 => 365 + case C366 => 366 + case C367 => 367 + case C368 => 368 + case C369 => 369 + case C370 => 370 + case C371 => 371 + case C372 => 372 + case C373 => 373 + case C374 => 374 + case C375 => 375 + case C376 => 376 + case C377 => 377 + case C378 => 378 + case C379 => 379 + case C380 => 380 + case C381 => 381 + case C382 => 382 + case C383 => 383 + case C384 => 384 + case C385 => 385 + case C386 => 386 + case C387 => 387 + case C388 => 388 + case C389 => 389 + case C390 => 390 + case C391 => 391 +// case C392 => 392 + case C393 => 393 + case C394 => 394 + case C395 => 395 + case C396 => 396 +// case C397 => 397 + case C398 => 398 + case C399 => 399 + case C400 => 400 + } +} diff --git a/tests/patmat/patmatexhaust.check b/tests/patmat/patmatexhaust.check new file mode 100644 index 000000000..ef2b578d6 --- /dev/null +++ b/tests/patmat/patmatexhaust.check @@ -0,0 +1,33 @@ +./tests/patmat/patmatexhaust.scala:7: warning: match may not be exhaustive. +It would fail on the following input: Baz + def ma1(x:Foo) = x match { + ^ +./tests/patmat/patmatexhaust.scala:11: warning: match may not be exhaustive. +It would fail on the following input: Bar(_) + def ma2(x:Foo) = x match { + ^ +./tests/patmat/patmatexhaust.scala:23: warning: match may not be exhaustive. +It would fail on the following input: (Qult(), Qult()), (Kult(_), Kult(_)) + def ma3(x:Mult) = (x,x) match { // not exhaustive + ^ +./tests/patmat/patmatexhaust.scala:49: warning: match may not be exhaustive. +It would fail on the following input: _: Gp + def ma4(x:Deep) = x match { // missing cases: Gu, Gp which is not abstract so must be included + ^ +./tests/patmat/patmatexhaust.scala:75: warning: match may not be exhaustive. +It would fail on the following input: _: B + def ma9(x: B) = x match { + ^ +./tests/patmat/patmatexhaust.scala:100: warning: match may not be exhaustive. +It would fail on the following input: _: C1 + def ma10(x: C) = x match { // not exhaustive: C1 is not sealed. + ^ +./tests/patmat/patmatexhaust.scala:114: warning: match may not be exhaustive. +It would fail on the following input: D2(), D1 + def ma10(x: C) = x match { // not exhaustive: C1 has subclasses. + ^ +./tests/patmat/patmatexhaust.scala:126: warning: match may not be exhaustive. +It would fail on the following input: _: C1 + def ma10(x: C) = x match { // not exhaustive: C1 is not abstract. + ^ +8 warnings found
\ No newline at end of file diff --git a/tests/patmat/patmatexhaust.scala b/tests/patmat/patmatexhaust.scala new file mode 100644 index 000000000..26f0c12a9 --- /dev/null +++ b/tests/patmat/patmatexhaust.scala @@ -0,0 +1,131 @@ +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 + } + } +} diff --git a/tests/patmat/sealed-java-enums.check b/tests/patmat/sealed-java-enums.check new file mode 100644 index 000000000..ed93d3d40 --- /dev/null +++ b/tests/patmat/sealed-java-enums.check @@ -0,0 +1,5 @@ +./tests/patmat/sealed-java-enums.scala:5: warning: match may not be exhaustive. +It would fail on the following input: TERMINATED, TIMED_WAITING, BLOCKED + def f(state: State) = state match { + ^ +one warning found diff --git a/tests/patmat/sealed-java-enums.scala b/tests/patmat/sealed-java-enums.scala new file mode 100644 index 000000000..2daf93f30 --- /dev/null +++ b/tests/patmat/sealed-java-enums.scala @@ -0,0 +1,10 @@ +import java.lang.Thread.State +import java.lang.Thread.State._ + +object Test { + def f(state: State) = state match { + case NEW | WAITING => true + case RUNNABLE => false + // and I forget the rest + } +} diff --git a/tests/patmat/t1056.scala b/tests/patmat/t1056.scala new file mode 100644 index 000000000..68f1ff273 --- /dev/null +++ b/tests/patmat/t1056.scala @@ -0,0 +1,5 @@ +object Test { + type T = PartialFunction[String,String] + def g(h: T) = () + g({case s: String => s}) +} diff --git a/tests/patmat/t2425.scala b/tests/patmat/t2425.scala new file mode 100644 index 000000000..477d5467a --- /dev/null +++ b/tests/patmat/t2425.scala @@ -0,0 +1,15 @@ +trait B +class D extends B +object Test extends App { + def foo[T](bar: T) = { + bar match { + case _: Array[Array[_]] => println("array 2d") + case _: Array[_] => println("array 1d") + case _ => println("something else") + } + } + foo(Array.fill(10)(2)) + foo(Array.fill(10, 10)(2)) + foo(Array.fill(10, 10, 10)(2)) + foo(List(1, 2, 3)) +} diff --git a/tests/patmat/t2442/MyEnum.java b/tests/patmat/t2442/MyEnum.java new file mode 100644 index 000000000..3ffbbb31b --- /dev/null +++ b/tests/patmat/t2442/MyEnum.java @@ -0,0 +1,3 @@ +public enum MyEnum { + ONE, TWO, THREE; +}
\ No newline at end of file diff --git a/tests/patmat/t2442/MySecondEnum.java b/tests/patmat/t2442/MySecondEnum.java new file mode 100644 index 000000000..0f841286d --- /dev/null +++ b/tests/patmat/t2442/MySecondEnum.java @@ -0,0 +1,6 @@ +public enum MySecondEnum { + RED(1), BLUE(2) { public void foo() {} }; + MySecondEnum(int i) {} + + public void foo() {} +}
\ No newline at end of file diff --git a/tests/patmat/t2442/expected.check b/tests/patmat/t2442/expected.check new file mode 100644 index 000000000..33110ce43 --- /dev/null +++ b/tests/patmat/t2442/expected.check @@ -0,0 +1,9 @@ +./tests/patmat/t2442/t2442.scala:4: warning: match may not be exhaustive. +It would fail on the following input: THREE + def f(e: MyEnum) = e match { + ^ +./tests/patmat/t2442/t2442.scala:11: warning: match may not be exhaustive. +It would fail on the following input: BLUE + def g(e: MySecondEnum) = e match { + ^ +two warnings found diff --git a/tests/patmat/t2442/t2442.scala b/tests/patmat/t2442/t2442.scala new file mode 100644 index 000000000..b0a0f3cd4 --- /dev/null +++ b/tests/patmat/t2442/t2442.scala @@ -0,0 +1,15 @@ +class Test { + import MyEnum._ + + def f(e: MyEnum) = e match { + case ONE => println("one") + case TWO => println("two") + // missing case --> exhaustivity warning! + } + + import MySecondEnum._ + def g(e: MySecondEnum) = e match { + case RED => println("red") + // missing case --> exhaustivity warning! + } +}
\ No newline at end of file diff --git a/tests/patmat/t3097.scala b/tests/patmat/t3097.scala new file mode 100644 index 000000000..3ff61b3c7 --- /dev/null +++ b/tests/patmat/t3097.scala @@ -0,0 +1,35 @@ +sealed trait ISimpleValue + +sealed trait IListValue extends ISimpleValue { + def items: List[IAtomicValue[_]] +} + +sealed trait IAtomicValue[O] extends ISimpleValue { + def data: O +} + +sealed trait IAbstractDoubleValue[O] extends IAtomicValue[O] { +} + +sealed trait IDoubleValue extends IAbstractDoubleValue[Double] + +case class ListValue(val items: List[IAtomicValue[_]]) extends IListValue + +class DoubleValue(val data: Double) extends IDoubleValue { + def asDouble = data +} + +object Test { + + /** + * @param args the command line arguments + */ + def main(args: Array[String]): Unit = { + val v: ISimpleValue = new DoubleValue(1) + v match { + case m: IListValue => println("list") + case a: IAtomicValue[_] => println("atomic") + } + + } +}
\ No newline at end of file diff --git a/tests/patmat/t3098/a.scala b/tests/patmat/t3098/a.scala new file mode 100644 index 000000000..57a103c7a --- /dev/null +++ b/tests/patmat/t3098/a.scala @@ -0,0 +1,6 @@ +// Traits.scala +sealed trait T + +trait A extends T +trait B extends T +trait C extends T diff --git a/tests/patmat/t3098/b.scala b/tests/patmat/t3098/b.scala new file mode 100644 index 000000000..84a1f9f6f --- /dev/null +++ b/tests/patmat/t3098/b.scala @@ -0,0 +1,8 @@ +// Test.scala +object Test { + def f = (null: T) match { + case _: A => println("A") + case _: B => println("B") + // no C + } +} diff --git a/tests/patmat/t3098/expected.check b/tests/patmat/t3098/expected.check new file mode 100644 index 000000000..331904111 --- /dev/null +++ b/tests/patmat/t3098/expected.check @@ -0,0 +1,5 @@ +./tests/patmat/t3098/b.scala:3: warning: match may not be exhaustive. +It would fail on the following input: _: C + def f = (null: T) match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t3111.check b/tests/patmat/t3111.check new file mode 100644 index 000000000..46ff0a6a9 --- /dev/null +++ b/tests/patmat/t3111.check @@ -0,0 +1,8 @@ +./tests/patmat/t3111.scala:4: warning: match may not be exhaustive. +It would fail on the following input: false + bool match { + ^ +./tests/patmat/t3111.scala:11: warning: unreachable code + case _ => "cats and dogs living together... mass hysteria!" + ^ +two warnings found
\ No newline at end of file diff --git a/tests/patmat/t3111.scala b/tests/patmat/t3111.scala new file mode 100644 index 000000000..8f2bc5a27 --- /dev/null +++ b/tests/patmat/t3111.scala @@ -0,0 +1,13 @@ +object Test { + val bool: Boolean = false + + bool match { + case true => "true!" + } + + bool match { + case true => "true!" + case false => "false!" + case _ => "cats and dogs living together... mass hysteria!" + } +}
\ No newline at end of file diff --git a/tests/patmat/t3163.check b/tests/patmat/t3163.check new file mode 100644 index 000000000..3da94e2c2 --- /dev/null +++ b/tests/patmat/t3163.check @@ -0,0 +1,5 @@ +./tests/patmat/t3163.scala:2: warning: match may not be exhaustive. +It would fail on the following input: _: AnyVal + def foo(x : AnyVal) = x match {case b : Boolean => "It's a bool"} + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t3163.scala b/tests/patmat/t3163.scala new file mode 100644 index 000000000..2e0f2c1d9 --- /dev/null +++ b/tests/patmat/t3163.scala @@ -0,0 +1,3 @@ +object Test { + def foo(x : AnyVal) = x match {case b : Boolean => "It's a bool"} +}
\ No newline at end of file diff --git a/tests/patmat/t3683.scala b/tests/patmat/t3683.scala new file mode 100644 index 000000000..44be9d6c6 --- /dev/null +++ b/tests/patmat/t3683.scala @@ -0,0 +1,19 @@ +sealed trait Foo +sealed trait Bar extends Foo +sealed trait W[T >: Bar <: Foo] +sealed case class X() extends W[Foo] +sealed case class Y() extends W[Bar] +sealed case class Z[T >: Bar <: Foo]( + z1: W[T] +) extends W[T] + +object Main { + def func(w: W[Bar]): Int = { + w match { + // Error if I include it, warning if I do not! + // case X() => 2 + case Y() => 1 + case Z(z) => func(z) + } + } +} diff --git a/tests/patmat/t3683a.check b/tests/patmat/t3683a.check new file mode 100644 index 000000000..df5e691c6 --- /dev/null +++ b/tests/patmat/t3683a.check @@ -0,0 +1,5 @@ +./tests/patmat/t3683a.scala:14: warning: match may not be exhaustive. +It would fail on the following input: XX() + w match { + ^ +one warning found diff --git a/tests/patmat/t3683a.scala b/tests/patmat/t3683a.scala new file mode 100644 index 000000000..6d1915213 --- /dev/null +++ b/tests/patmat/t3683a.scala @@ -0,0 +1,20 @@ +sealed trait Foo +sealed trait Bar extends Foo +sealed trait W[T >: Bar <: Foo] +case class X() extends W[Foo] +case class XX() extends W[Bar] +case class Y() extends W[Bar] +case class Z[T >: Bar <: Foo]( + z1: W[T] +) extends W[T] + +object Main { + // should warn for not including XX() + def f1(w: W[Bar]): Int = { + w match { + // case XX() => 2 + case Y() => 1 + case Z(z) => f1(z) + } + } +}
\ No newline at end of file diff --git a/tests/patmat/t4020.scala b/tests/patmat/t4020.scala new file mode 100644 index 000000000..f97646019 --- /dev/null +++ b/tests/patmat/t4020.scala @@ -0,0 +1,25 @@ +class A { + sealed trait Foo +} + +object a1 extends A { + case class Foo1(i: Int) extends Foo +} + +object a2 extends A { + case class Foo2(i: Int) extends Foo +} + +class B { + def mthd(foo: a2.Foo) = { + foo match { + case a2.Foo2(i) => i + + // Note: This case is impossible. In fact, scalac + // will (correctly) report an error if it is uncommented, + // but a warning if it is commented. + + // case a1.Foo1(i) => i + } + } +}
\ No newline at end of file diff --git a/tests/patmat/t4333.scala.ignore b/tests/patmat/t4333.scala.ignore new file mode 100644 index 000000000..07d105c74 --- /dev/null +++ b/tests/patmat/t4333.scala.ignore @@ -0,0 +1,7 @@ +object Enum extends Enumeration { val A, B, C = Value } + +object Test { + def foo(v : Enum.Value) = v match { + case Enum.B => println("B") + } +} diff --git a/tests/patmat/t4408.check b/tests/patmat/t4408.check new file mode 100644 index 000000000..53bfe1c2c --- /dev/null +++ b/tests/patmat/t4408.check @@ -0,0 +1,5 @@ +./tests/patmat/t4408.scala:2: warning: match may not be exhaustive. +It would fail on the following input: List(_, _, _) + def printList(in: List[String]): Unit = in match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t4408.scala b/tests/patmat/t4408.scala new file mode 100644 index 000000000..419b66369 --- /dev/null +++ b/tests/patmat/t4408.scala @@ -0,0 +1,16 @@ +object Test { + def printList(in: List[String]): Unit = in match { + case Nil => Unit + + case (s: String) :: Nil => + println(s) + + case head :: (s: String) :: Nil => + printList(head :: Nil) + for(i <- head){ + print(i) + } + println + println(s) + } +} diff --git a/tests/patmat/t4526.check b/tests/patmat/t4526.check new file mode 100644 index 000000000..b577cbc0c --- /dev/null +++ b/tests/patmat/t4526.check @@ -0,0 +1,13 @@ +./tests/patmat/t4526.scala:2: warning: match may not be exhaustive. +It would fail on the following input: _: Int + def foo(a: Int) = a match { + ^ +./tests/patmat/t4526.scala:7: warning: match may not be exhaustive. +It would fail on the following input: (_, _) + def bar(a: (Int, Int)) = a match { + ^ +./tests/patmat/t4526.scala:12: warning: match may not be exhaustive. +It would fail on the following input: (false, false), (true, true) + def baz(a: (Boolean, Boolean)) = a match { + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/t4526.scala b/tests/patmat/t4526.scala new file mode 100644 index 000000000..d531c6b34 --- /dev/null +++ b/tests/patmat/t4526.scala @@ -0,0 +1,16 @@ +object Test{ + def foo(a: Int) = a match { + case 5 => "Five!" + case 42 => "The answer." + } + + def bar(a: (Int, Int)) = a match { + case (5, 5) => "Two fives!" + case (42, 21) => "The answer and a half." + } + + def baz(a: (Boolean, Boolean)) = a match { + case (true, false) => "tf" + case (false, true) => "ft" + } +}
\ No newline at end of file diff --git a/tests/patmat/t4691.check b/tests/patmat/t4691.check new file mode 100644 index 000000000..4d2c24506 --- /dev/null +++ b/tests/patmat/t4691.check @@ -0,0 +1,5 @@ +./tests/patmat/t4691.scala:15: warning: match may not be exhaustive. +It would fail on the following input: NodeType2(_) + def test (x: Node) = x match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t4691.scala b/tests/patmat/t4691.scala new file mode 100644 index 000000000..bfaa61670 --- /dev/null +++ b/tests/patmat/t4691.scala @@ -0,0 +1,18 @@ +sealed trait Node + +class NodeType1 (val a:Int) extends Node +class NodeType2 (val b:Int) extends Node + +object NodeType1 { + def unapply (x : NodeType1) : Some[Int] = Some(x.a) +} + +object NodeType2 { + def unapply (x : NodeType2) : Some[Int] = Some(x.b) +} + +object Test { + def test (x: Node) = x match { + case NodeType1(a) => "got node type 1 " + a + } +}
\ No newline at end of file diff --git a/tests/patmat/t4691_exhaust_extractor.check b/tests/patmat/t4691_exhaust_extractor.check new file mode 100644 index 000000000..e7d1e17f9 --- /dev/null +++ b/tests/patmat/t4691_exhaust_extractor.check @@ -0,0 +1,13 @@ +./tests/patmat/t4691_exhaust_extractor.scala:17: warning: match may not be exhaustive. +It would fail on the following input: _: Bar3 + def f1(x: Foo) = x match { + ^ +./tests/patmat/t4691_exhaust_extractor.scala:23: warning: match may not be exhaustive. +It would fail on the following input: _: Bar3 + def f2(x: Foo) = x match { + ^ +./tests/patmat/t4691_exhaust_extractor.scala:29: warning: match may not be exhaustive. +It would fail on the following input: _: Bar3 + def f3(x: Foo) = x match { + ^ +three warnings found diff --git a/tests/patmat/t4691_exhaust_extractor.scala b/tests/patmat/t4691_exhaust_extractor.scala new file mode 100644 index 000000000..c68c33d65 --- /dev/null +++ b/tests/patmat/t4691_exhaust_extractor.scala @@ -0,0 +1,33 @@ +sealed trait Foo +class Bar1 extends Foo +class Bar2 extends Foo +class Bar3 extends Foo + +// these extractors are known to always succeed as they return a Some +object Baz1 { + def unapply(x: Bar1): Some[Int] = Some(1) +} +object Baz2 { + def unapply(x: Bar2): Some[Int] = Some(2) +} + + +object Test { + // warning: missing Bar3 + def f1(x: Foo) = x match { + case _: Bar1 => 1 + case _: Bar2 => 2 + } + + // warning: missing Bar3 + def f2(x: Foo) = x match { + case _: Bar1 => 1 + case Baz2(x) => x + } + + // warning: missing Bar3 + def f3(x: Foo) = x match { + case Baz1(x) => x + case Baz2(x) => x + } +}
\ No newline at end of file diff --git a/tests/patmat/t5440.check b/tests/patmat/t5440.check new file mode 100644 index 000000000..0780d6529 --- /dev/null +++ b/tests/patmat/t5440.check @@ -0,0 +1,5 @@ +./tests/patmat/t5440.scala:2: warning: match may not be exhaustive. +It would fail on the following input: (Nil, List(_)), (List(_), Nil) + def merge(list1: List[Long], list2: List[Long]): Boolean = (list1, list2) match { + ^ +one warning found diff --git a/tests/patmat/t5440.scala b/tests/patmat/t5440.scala new file mode 100644 index 000000000..6721b0562 --- /dev/null +++ b/tests/patmat/t5440.scala @@ -0,0 +1,6 @@ +object Test { + def merge(list1: List[Long], list2: List[Long]): Boolean = (list1, list2) match { + case (hd1::_, hd2::_) => true + case (Nil, Nil) => true + } +}
\ No newline at end of file diff --git a/tests/patmat/t5968.scala b/tests/patmat/t5968.scala new file mode 100644 index 000000000..14cc903c8 --- /dev/null +++ b/tests/patmat/t5968.scala @@ -0,0 +1,7 @@ +object Test { + object X + def f(e: Either[Int, X.type]) = e match { + case Left(i) => i + case Right(X) => 0 + } +}
\ No newline at end of file diff --git a/tests/patmat/t6008.scala b/tests/patmat/t6008.scala new file mode 100644 index 000000000..c42e9c5a5 --- /dev/null +++ b/tests/patmat/t6008.scala @@ -0,0 +1,5 @@ +object Test { + def x(in: (Int, Boolean)) = in match { + case (i: Int, b: Boolean) => 3 + } +}
\ No newline at end of file diff --git a/tests/patmat/t6146.scala b/tests/patmat/t6146.scala new file mode 100644 index 000000000..b5bde826b --- /dev/null +++ b/tests/patmat/t6146.scala @@ -0,0 +1,60 @@ +// No unreachable or exhaustiveness warnings, please. + +// +// The reported bug +// + +trait AxisCompanion { + sealed trait Format + object Format { + case object Decimal extends Format + case object Integer extends Format + // Gives an unrelated warning: The outer reference in this type test cannot be checked at run time. + //final case class Time( hours: Boolean = false, millis: Boolean = true ) extends Format + } +} +object Axis extends AxisCompanion +class Axis { + import Axis._ + def test( f: Format ) = f match { + case Format.Integer => "Int" + // case Format.Time( hours, millis ) => "Time" + case Format.Decimal => "Dec" + } +} + + +// +// Some tricksier variations +// + +trait T1[X] { + trait T2[Y] { + sealed trait Format + object Format { + case object Decimal extends Format + case object Integer extends Format + } + } +} + +object O1 extends T1[Any] { + object O2 extends T2[Any] { + + } +} + +case object Shorty extends O1.O2.Format + +class Test1 { + import O1.O2._ + val FI: Format.Integer.type = Format.Integer + def test( f: Format ) = { + val ff: f.type = f + ff match { + case FI => "Int" + case Format.Decimal => "Dec" + case Shorty => "Sho" + } + } +} diff --git a/tests/patmat/t6420.check b/tests/patmat/t6420.check new file mode 100644 index 000000000..c62b33d18 --- /dev/null +++ b/tests/patmat/t6420.check @@ -0,0 +1,5 @@ +./tests/patmat/t6420.scala:5: warning: match may not be exhaustive. +It would fail on the following input: (Nil, _), (List(_, _), _), (Nil, Nil), (Nil, List(_, _)), (List(_, _), Nil), (List(_, _), List(_, _)), (_, Nil), (_, List(_, _)) + def foo(x: List[Boolean], y: List[Boolean]) = (x,y) match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t6420.scala b/tests/patmat/t6420.scala new file mode 100644 index 000000000..80c0f90f6 --- /dev/null +++ b/tests/patmat/t6420.scala @@ -0,0 +1,11 @@ +object Test { + val c0 = false + val c1 = true + + def foo(x: List[Boolean], y: List[Boolean]) = (x,y) match { + case (`c0`::x, `c0`::y) => x + case (`c0`::x, `c1`::y) => y + case (`c1`::x, `c0`::y) => y + case (`c1`::x, `c1`::y) => x + } +} diff --git a/tests/patmat/t6450.scala b/tests/patmat/t6450.scala new file mode 100644 index 000000000..157f1ce81 --- /dev/null +++ b/tests/patmat/t6450.scala @@ -0,0 +1,9 @@ +sealed abstract class FoundNode[T] +// case class A[T](x: T) extends FoundNode[T] + +object Foo { + val v: (Some[_], FoundNode[_]) = (???, ???) + v match { + case (x: Some[t], _) => + } +} diff --git a/tests/patmat/t6582_exhaust_big.check b/tests/patmat/t6582_exhaust_big.check new file mode 100644 index 000000000..c244e5ba5 --- /dev/null +++ b/tests/patmat/t6582_exhaust_big.check @@ -0,0 +1,5 @@ +./tests/patmat/t6582_exhaust_big.scala:27: warning: match may not be exhaustive. +It would fail on the following input: Z.Z11() + def foo(z: Z) = z match { + ^ +one warning found diff --git a/tests/patmat/t6582_exhaust_big.scala b/tests/patmat/t6582_exhaust_big.scala new file mode 100644 index 000000000..dd639eb56 --- /dev/null +++ b/tests/patmat/t6582_exhaust_big.scala @@ -0,0 +1,32 @@ +sealed abstract class Z +object Z { + object Z0 extends Z + case class Z1() extends Z + object Z2 extends Z + case class Z3() extends Z + object Z4 extends Z + case class Z5() extends Z + object Z6 extends Z + case class Z7() extends Z + object Z8 extends Z + case class Z9() extends Z + object Z10 extends Z + case class Z11() extends Z + object Z12 extends Z + case class Z13() extends Z + object Z14 extends Z + case class Z15() extends Z + object Z16 extends Z + case class Z17() extends Z + object Z18 extends Z + case class Z19() extends Z +} + +object Test { + import Z._ + def foo(z: Z) = z match { + case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() | + Z10 | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19() + => + } +} diff --git a/tests/patmat/t6818.scala b/tests/patmat/t6818.scala new file mode 100644 index 000000000..2334095c4 --- /dev/null +++ b/tests/patmat/t6818.scala @@ -0,0 +1,11 @@ +object Test { + type Id[X] = X + + def foo(x:Id[Option[Int]]) = x match { + case Some(n) => "foo" + case None => "bar" + } + + foo(Some(3)) // "foo" + foo(None) // "bar" +}
\ No newline at end of file diff --git a/tests/patmat/t7020.check b/tests/patmat/t7020.check new file mode 100644 index 000000000..c091535ae --- /dev/null +++ b/tests/patmat/t7020.check @@ -0,0 +1,17 @@ +./tests/patmat/t7020.scala:3: warning: match may not be exhaustive. +It would fail on the following input: List(_, _) + List(5) match { + ^ +./tests/patmat/t7020.scala:10: warning: match may not be exhaustive. +It would fail on the following input: List(_, _) + List(5) match { + ^ +./tests/patmat/t7020.scala:17: warning: match may not be exhaustive. +It would fail on the following input: List(_, _) + List(5) match { + ^ +./tests/patmat/t7020.scala:24: warning: match may not be exhaustive. +It would fail on the following input: List(_, _) + List(5) match { + ^ +four warnings found diff --git a/tests/patmat/t7020.scala b/tests/patmat/t7020.scala new file mode 100644 index 000000000..cc5421bab --- /dev/null +++ b/tests/patmat/t7020.scala @@ -0,0 +1,30 @@ +object Test { + // warning was non-deterministic + List(5) match { + case 1 :: Nil | 2 :: Nil => + case (x@(4 | 5 | 6)) :: Nil => + case 7 :: Nil => + case Nil => + } + + List(5) match { + case 1 :: Nil | 2 :: Nil => + case (x@(4 | 5 | 6)) :: Nil => + case 7 :: Nil => + case Nil => + } + + List(5) match { + case 1 :: Nil | 2 :: Nil => + case (x@(4 | 5 | 6)) :: Nil => + case 7 :: Nil => + case Nil => + } + + List(5) match { + case 1 :: Nil | 2 :: Nil => + case (x@(4 | 5 | 6)) :: Nil => + case 7 :: Nil => + case Nil => + } +} diff --git a/tests/patmat/t7206.scala.ignore b/tests/patmat/t7206.scala.ignore new file mode 100644 index 000000000..0133f1808 --- /dev/null +++ b/tests/patmat/t7206.scala.ignore @@ -0,0 +1,19 @@ +object E extends Enumeration { + val V = Value +} + +sealed case class C(e: E.Value) + +class Test { + def foo(c: C) = { + c match { + case C(E.V) => {} + } + } + + def foo2(e: E.Value) = { + e match { + case E.V => {} + } + } +} diff --git a/tests/patmat/t7285.check b/tests/patmat/t7285.check new file mode 100644 index 000000000..703706cdc --- /dev/null +++ b/tests/patmat/t7285.check @@ -0,0 +1,13 @@ +./tests/patmat/t7285.scala:15: warning: match may not be exhaustive. +It would fail on the following input: (Up, Down) + (d1, d2) match { + ^ +./tests/patmat/t7285.scala:33: warning: match may not be exhaustive. +It would fail on the following input: Down + (d1) match { + ^ +./tests/patmat/t7285.scala:51: warning: match may not be exhaustive. +It would fail on the following input: (Base.Up, Base.Down) + (d1, d2) match { + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/t7285.scala b/tests/patmat/t7285.scala new file mode 100644 index 000000000..d40df7fe8 --- /dev/null +++ b/tests/patmat/t7285.scala @@ -0,0 +1,55 @@ +sealed abstract class Base + + +object Test1 { + sealed abstract class Base + + object Base { + case object Down extends Base { + } + + case object Up extends Base { + } + + def foo(d1: Base, d2: Base) = + (d1, d2) match { + case (Up, Up) | (Down, Down) => false + case (Down, Up) => true + } + } +} + +object Test2 { + sealed abstract class Base + + object Base { + case object Down extends Base { + } + + case object Up extends Base { + } + + def foo(d1: Base, d2: Base) = + (d1) match { + case Test2.Base.Up => false + } + } +} + + +object Test4 { + sealed abstract class Base + + object Base { + case object Down extends Base + + case object Up extends Base + } + + import Test4.Base._ + def foo(d1: Base, d2: Base) = + (d1, d2) match { + case (Up, Up) | (Down, Down) => false + case (Down, Test4.Base.Up) => true + } +} diff --git a/tests/patmat/t7285a.scala b/tests/patmat/t7285a.scala new file mode 100644 index 000000000..49f6b663b --- /dev/null +++ b/tests/patmat/t7285a.scala @@ -0,0 +1,83 @@ +sealed abstract class Base + +object Test { + case object Up extends Base + + def foo(d1: Base) = + d1 match { + case Up => + } + + // Sealed subtype: ModuleTypeRef <empty>.this.Test.Up.type + // Pattern: UniqueThisType Test.this.type +} + + +object Test1 { + sealed abstract class Base + + object Base { + case object Down extends Base { + } + + case object Up extends Base { + } + + def foo(d1: Base, d2: Base) = + (d1, d2) match { + case (Up, Up) | (Down, Down) => false + case (Down, Up) => true + case (Up, Down) => false + } + } +} + +object Test2 { + sealed abstract class Base + + object Base { + case object Down extends Base { + } + + case object Up extends Base { + } + + def foo(d1: Base, d2: Base) = + (d1) match { + case Up | Down => false + } + } +} + +object Test3 { + sealed abstract class Base + + object Base { + case object Down extends Base + + def foo(d1: Base, d2: Base) = + (d1, d2) match { + case (Down, Down) => false + } + } +} + +object Test4 { + sealed abstract class Base + + object Base { + case object Down extends Base { + } + + case object Up extends Base { + } + + } + import Test4.Base._ + def foo(d1: Base, d2: Base) = + (d1, d2) match { + case (Up, Up) | (Down, Down) => false + case (Down, Test4.Base.Up) => true + case (Up, Down) => false + } +} diff --git a/tests/patmat/t7298.scala b/tests/patmat/t7298.scala new file mode 100644 index 000000000..6fba5e120 --- /dev/null +++ b/tests/patmat/t7298.scala @@ -0,0 +1,11 @@ +sealed trait Bool + +object Bool { + case object FALSE extends Bool + case object TRUE extends Bool + + def show(b: Bool) = b match { + case FALSE => "1" + case TRUE => "2" + } +} diff --git a/tests/patmat/t7353.scala b/tests/patmat/t7353.scala new file mode 100644 index 000000000..7a8fea115 --- /dev/null +++ b/tests/patmat/t7353.scala @@ -0,0 +1,11 @@ +sealed trait EthernetType + +object EthernetType { + final case object Gigabit extends EthernetType + final case object FastEthernet extends EthernetType + + final def toInt(t: EthernetType) = t match { + case Gigabit => 1 + case FastEthernet => 2 + } +}
\ No newline at end of file diff --git a/tests/patmat/t7437.scala b/tests/patmat/t7437.scala new file mode 100644 index 000000000..b0c5dff7c --- /dev/null +++ b/tests/patmat/t7437.scala @@ -0,0 +1,17 @@ +sealed trait IntegralNumber +sealed trait FiniteNumber extends IntegralNumber + +object IntegralNumber { + + sealed abstract class BaseNumber extends IntegralNumber + sealed abstract class NonFinite extends BaseNumber + object NaN extends NonFinite + sealed abstract class FiniteNumberImpl[N](val value: N) extends BaseNumber with FiniteNumber + sealed class IntNumber(value: Int) extends FiniteNumberImpl[Int](value) + + def test(t: IntNumber, o: IntegralNumber) = o match { + case NaN => -1 + case o: IntNumber => t.value.compare(o.value) + } + +}
\ No newline at end of file diff --git a/tests/patmat/t7466.check b/tests/patmat/t7466.check new file mode 100644 index 000000000..8e575f6a2 --- /dev/null +++ b/tests/patmat/t7466.check @@ -0,0 +1,5 @@ +./tests/patmat/t7466.scala:8: warning: match may not be exhaustive. +It would fail on the following input: (_, _) + (b1, b2) match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t7466.scala b/tests/patmat/t7466.scala new file mode 100644 index 000000000..a74bf4ee2 --- /dev/null +++ b/tests/patmat/t7466.scala @@ -0,0 +1,17 @@ +object Test extends App { + val Yes1 = true + val Yes2 = true + val No1 = false + val No2 = false + + def test(b1: Boolean, b2: Boolean) = { + (b1, b2) match { + case (No1, No2) => println("1") + case (No1, Yes2) => println("2") + case (Yes1, No2) => println("3") + case (Yes1, Yes2) => println("4") + } + } + + test(No1, Yes2) +}
\ No newline at end of file diff --git a/tests/patmat/t7631.check b/tests/patmat/t7631.check new file mode 100644 index 000000000..ede3703e2 --- /dev/null +++ b/tests/patmat/t7631.check @@ -0,0 +1,5 @@ +./tests/patmat/t7631.scala:8: warning: match may not be exhaustive. +It would fail on the following input: TestB() + val x = input match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t7631.scala b/tests/patmat/t7631.scala new file mode 100644 index 000000000..13e74183f --- /dev/null +++ b/tests/patmat/t7631.scala @@ -0,0 +1,11 @@ +sealed trait Test +case class TestA() extends Test +case class TestB() extends Test + +object Tester { + val input : Test = TestA() + val num = 3 + val x = input match { + case TestA() if num == 3 => 2 + } +}
\ No newline at end of file diff --git a/tests/patmat/t7669.check b/tests/patmat/t7669.check new file mode 100644 index 000000000..2804dbf5c --- /dev/null +++ b/tests/patmat/t7669.check @@ -0,0 +1,5 @@ +./tests/patmat/t7669.scala:10: warning: match may not be exhaustive. +It would fail on the following input: NotHandled(_) + def exhausto(expr: Expr): Unit = expr match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t7669.scala b/tests/patmat/t7669.scala new file mode 100644 index 000000000..3aa74129e --- /dev/null +++ b/tests/patmat/t7669.scala @@ -0,0 +1,14 @@ +object Test { + + sealed abstract class Expr + // Change type of `arg` to `Any` and the exhaustiveness warning + // is issued below + case class Op(arg: Expr) extends Expr + case class NotHandled(num: Double) extends Expr + + + def exhausto(expr: Expr): Unit = expr match { + case Op(Op(_)) => + case Op(_) => + } +} diff --git a/tests/patmat/t7746.check b/tests/patmat/t7746.check new file mode 100644 index 000000000..be4c53570 --- /dev/null +++ b/tests/patmat/t7746.check @@ -0,0 +1,5 @@ +./tests/patmat/t7746.scala:2: warning: match may not be exhaustive. +It would fail on the following input: Some(_), None + def f[T](x: Option[T]) = x match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t7746.scala b/tests/patmat/t7746.scala new file mode 100644 index 000000000..91f3823a4 --- /dev/null +++ b/tests/patmat/t7746.scala @@ -0,0 +1,5 @@ +object Test { + def f[T](x: Option[T]) = x match { + case Some(Some(5)) => true + } +}
\ No newline at end of file diff --git a/tests/patmat/t8068.scala b/tests/patmat/t8068.scala new file mode 100644 index 000000000..9837b7381 --- /dev/null +++ b/tests/patmat/t8068.scala @@ -0,0 +1,14 @@ +trait K[A] { + sealed trait T + case class C(x: Int) extends T + case object O extends T +} + +object Hello { + def f[A](k: K[A])(t: k.T) = { + t match { + case k.C(x) => ??? + case k.O => ??? + } + } +} diff --git a/tests/patmat/t8178.check b/tests/patmat/t8178.check new file mode 100644 index 000000000..963845f53 --- /dev/null +++ b/tests/patmat/t8178.check @@ -0,0 +1,13 @@ +./tests/patmat/t8178.scala:6: warning: match may not be exhaustive. +It would fail on the following input: FailsChild2(_) + f match { + ^ +./tests/patmat/t8178.scala:14: warning: match may not be exhaustive. +It would fail on the following input: VarArgs1(_) + f match { + ^ +./tests/patmat/t8178.scala:27: warning: match may not be exhaustive. +It would fail on the following input: SeqArgs2(_) + f match { + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/t8178.scala b/tests/patmat/t8178.scala new file mode 100644 index 000000000..4fb39955b --- /dev/null +++ b/tests/patmat/t8178.scala @@ -0,0 +1,33 @@ +sealed trait Fails +case class VarArgs1(a: String*) extends Fails +case class FailsChild2(a: Seq[String]) extends Fails +object FailsTest { + def matchOnVarArgsFirstFails(f: Fails) = { + f match { + case VarArgs1(_) => ??? + // BUG: Without this line we should get a non-exhaustive match compiler error. + //case FailsChild2(_) => ??? + } + } + + def matchOnSeqArgsFirstWorks(f: Fails) = { + f match { + case FailsChild2(_) => ??? + // Without this line, the compiler reports a "match may not be exhaustive" error as expected. + // case VarArgs1(_) => ??? + } + } +} + +sealed trait Works +case class SeqArgs1(a: Seq[String]) extends Works +case class SeqArgs2(a: Seq[String]) extends Works +object WorksTest { + def matcher(f: Works) = { + f match { + case SeqArgs1(_) => ??? + // Without this line, the compiler reports a "match may not be exhaustive" error as expected. + // case SeqArgs2(_) => ??? + } + } +}
\ No newline at end of file diff --git a/tests/patmat/t8412.check b/tests/patmat/t8412.check new file mode 100644 index 000000000..b82b33999 --- /dev/null +++ b/tests/patmat/t8412.check @@ -0,0 +1,5 @@ +./tests/patmat/t8412.scala:7: warning: match may not be exhaustive. +It would fail on the following input: Lit(_) + tree match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t8412.scala b/tests/patmat/t8412.scala new file mode 100644 index 000000000..f4b2b6090 --- /dev/null +++ b/tests/patmat/t8412.scala @@ -0,0 +1,14 @@ +sealed trait Tree +case class Let(sth: List[Any]) extends Tree +case class Lit(sth: Any) extends Tree + +object Test { + def wroong(tree: Tree) = + tree match { + case Let(_ :: rest) => + ??? + case Let(Nil) => + ??? + // no warning for missing Lit(_) in 2.10 + } +} diff --git a/tests/patmat/t8430.check b/tests/patmat/t8430.check new file mode 100644 index 000000000..4493062bf --- /dev/null +++ b/tests/patmat/t8430.check @@ -0,0 +1,5 @@ +./tests/patmat/t8430.scala:15: warning: match may not be exhaustive. +It would fail on the following input: LetF, LetC, LetP, LetL(UnitLit), LetL(BooleanLit), LetL(IntLit) + def transform(tree: Tree) : Any = tree match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t8430.scala b/tests/patmat/t8430.scala new file mode 100644 index 000000000..ccd4585d9 --- /dev/null +++ b/tests/patmat/t8430.scala @@ -0,0 +1,19 @@ +sealed trait CL3Literal +case object IntLit extends CL3Literal +case object CharLit extends CL3Literal +case object BooleanLit extends CL3Literal +case object UnitLit extends CL3Literal + + +sealed trait Tree +case class LetL(value: CL3Literal) extends Tree +case object LetP extends Tree +case object LetC extends Tree +case object LetF extends Tree + +object Test { + def transform(tree: Tree) : Any = tree match { + case LetL(CharLit) => + ??? + } +} diff --git a/tests/patmat/t8511.check b/tests/patmat/t8511.check new file mode 100644 index 000000000..df07d019a --- /dev/null +++ b/tests/patmat/t8511.check @@ -0,0 +1,5 @@ +./tests/patmat/t8511.scala:18: warning: match may not be exhaustive. +It would fail on the following input: Baz(), Bar(_) + private def logic(head: Expr): String = head match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t8511.scala b/tests/patmat/t8511.scala new file mode 100644 index 000000000..bc7f64713 --- /dev/null +++ b/tests/patmat/t8511.scala @@ -0,0 +1,25 @@ +sealed trait Expr +final case class Foo(other: Option[String]) extends Expr +final case class Bar(someConstant: String) extends Expr +final case class Baz() extends Expr +final case class EatsExhaustiveWarning(other: Reference) extends Expr + +sealed trait Reference { + val value: String +} + +object Reference { + def unapply(reference: Reference): Option[(String)] = { + Some(reference.value) + } +} + +object EntryPoint { + private def logic(head: Expr): String = head match { + case Foo(_) => + ??? + // Commenting this line only causes the exhaustive search warning to be emitted + case EatsExhaustiveWarning(Reference(text)) => + ??? + } +}
\ No newline at end of file diff --git a/tests/patmat/t8546.scala b/tests/patmat/t8546.scala new file mode 100644 index 000000000..c39d749b4 --- /dev/null +++ b/tests/patmat/t8546.scala @@ -0,0 +1,49 @@ +package test + +class F1() { + private sealed abstract class T + private case class A(m: Int) extends T + private case class B() extends T + private case object C extends T + + // No warnings here + private def foo(t: T) = t match { + case A(m) => println("A:" + m) + case B() => println("B") + case C => println("C") + } + + def test(m: Int): Unit = { + foo(A(m)) + foo(B()) + foo(C) + } +} + +class F2[M]() { + private sealed abstract class T + private case class A(m: M) extends T + private case class B() extends T + private case object C extends T + + // match may not be exhaustive. It would fail on the following input: C + private def foo(t: T) = t match { + case A(m) => println("A:" + m) + case B() => println("B") + case C => println("C") + } + + def test(m: M): Unit = { + foo(A(m)) + foo(B()) + foo(C) + } + +} + +object Test { + def main(args: Array[String]): Unit = { + new F1().test(1) + new F2[Int]().test(1) + } +}
\ No newline at end of file diff --git a/tests/patmat/t8606.scala b/tests/patmat/t8606.scala new file mode 100644 index 000000000..9388c9f02 --- /dev/null +++ b/tests/patmat/t8606.scala @@ -0,0 +1,18 @@ +class Cl[T] { + + sealed trait A { + def foo = this match { + case AObj => 0 + case BObj => 0 + case ACls(x) => 0 + case BCls(x) => 0 + } + } + + case object AObj extends A + case class ACls(x: Int) extends A + + sealed trait B extends A + case object BObj extends B + case class BCls(x: Int) extends B +} diff --git a/tests/patmat/t8700a/Bar.scala b/tests/patmat/t8700a/Bar.scala new file mode 100644 index 000000000..33ad8e987 --- /dev/null +++ b/tests/patmat/t8700a/Bar.scala @@ -0,0 +1,9 @@ +object Bar { + def bar1(foo: Foo) = foo match { + case Foo.A => 1 + } + + def bar2(foo: Baz) = foo match { + case Baz.A => 1 + } +} diff --git a/tests/patmat/t8700a/Baz.java b/tests/patmat/t8700a/Baz.java new file mode 100644 index 000000000..49f15e121 --- /dev/null +++ b/tests/patmat/t8700a/Baz.java @@ -0,0 +1,11 @@ +public enum Baz { + A { + public void baz1() {} + }, + B { + public void baz1() {} + }; + + public abstract void baz1(); + public void baz2() {} +} diff --git a/tests/patmat/t8700a/Foo.java b/tests/patmat/t8700a/Foo.java new file mode 100644 index 000000000..cc8e9daf1 --- /dev/null +++ b/tests/patmat/t8700a/Foo.java @@ -0,0 +1,4 @@ +public enum Foo { + A, + B +} diff --git a/tests/patmat/t8700a/expected.check b/tests/patmat/t8700a/expected.check new file mode 100644 index 000000000..83f1c5a9e --- /dev/null +++ b/tests/patmat/t8700a/expected.check @@ -0,0 +1,9 @@ +./tests/patmat/t8700a/Bar.scala:2: warning: match may not be exhaustive. +It would fail on the following input: B + def bar1(foo: Foo) = foo match { + ^ +./tests/patmat/t8700a/Bar.scala:6: warning: match may not be exhaustive. +It would fail on the following input: B + def bar2(foo: Baz) = foo match { + ^ +two warnings found diff --git a/tests/patmat/t9129.check b/tests/patmat/t9129.check new file mode 100644 index 000000000..aa722a61a --- /dev/null +++ b/tests/patmat/t9129.check @@ -0,0 +1,5 @@ +./tests/patmat/t9129.scala:21: warning: match may not be exhaustive. +It would fail on the following input: Two(B2, A2), Two(_, A2) + def foo(c: C): Unit = c match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t9129.scala b/tests/patmat/t9129.scala new file mode 100644 index 000000000..89f08f0ac --- /dev/null +++ b/tests/patmat/t9129.scala @@ -0,0 +1,29 @@ +object Test { + + sealed abstract class A + + case object A1 extends A + + case object A2 extends A + + sealed abstract class B + + case object B1 extends B + + case object B2 extends B + + sealed abstract class C + + final case class One(a: A, b: B) extends C + + final case class Two(b: B, a: A) extends C + + def foo(c: C): Unit = c match { + case One(A1, B1) => + case One(A2, B1) => + case One(A1, B2) => + case One(A2, B2) => + case Two(B1, A1) => + case Two(B2, A1) => + } +}
\ No newline at end of file diff --git a/tests/patmat/t9232.check b/tests/patmat/t9232.check new file mode 100644 index 000000000..c3957c0ff --- /dev/null +++ b/tests/patmat/t9232.check @@ -0,0 +1,5 @@ +./tests/patmat/t9232.scala:13: warning: match may not be exhaustive. +It would fail on the following input: Node2() + def transformTree(tree: Tree): Any = tree match { + ^ +one warning found diff --git a/tests/patmat/t9232.scala b/tests/patmat/t9232.scala new file mode 100644 index 000000000..975ec58db --- /dev/null +++ b/tests/patmat/t9232.scala @@ -0,0 +1,16 @@ +final class Foo(val value: Int) + +object Foo { + def unapplySeq(foo: Foo): Some[Seq[Int]] = Some(List(foo.value)) + // def unapply(foo: Foo): Some[Int] = Some(foo.value) +} + +sealed trait Tree +case class Node1(foo: Foo) extends Tree +case class Node2() extends Tree + +object Test { + def transformTree(tree: Tree): Any = tree match { + case Node1(Foo(1)) => ??? + } +} diff --git a/tests/patmat/t9289.check b/tests/patmat/t9289.check new file mode 100644 index 000000000..5240988e2 --- /dev/null +++ b/tests/patmat/t9289.check @@ -0,0 +1,9 @@ +./tests/patmat/t9289.scala:9: warning: match may not be exhaustive. +It would fail on the following input: module.LetR() + def patmat(tree: module.Tree) = tree match { + ^ +./tests/patmat/t9289.scala:20: warning: match may not be exhaustive. +It would fail on the following input: module.LetR() + def patmat(tree: module.Tree) = tree match { + ^ +two warnings found
\ No newline at end of file diff --git a/tests/patmat/t9289.scala b/tests/patmat/t9289.scala new file mode 100644 index 000000000..714a4a0e3 --- /dev/null +++ b/tests/patmat/t9289.scala @@ -0,0 +1,28 @@ +trait Module { + sealed trait Tree + + case class LetL() extends Tree + case class LetR() extends Tree +} + +class Patmat[T <: Module](val module: T) { + def patmat(tree: module.Tree) = tree match { + case module.LetL() => ??? + } + + def exhaust(tree: module.Tree) = tree match { + case module.LetL() => ??? + case module.LetR() => ??? + } +} + +class Patmat2(val module: Module) { + def patmat(tree: module.Tree) = tree match { + case module.LetL() => ??? + } + + def exhaust(tree: module.Tree) = tree match { + case module.LetL() => ??? + case module.LetR() => ??? + } +} diff --git a/tests/patmat/t9351.check b/tests/patmat/t9351.check new file mode 100644 index 000000000..03b94c2c0 --- /dev/null +++ b/tests/patmat/t9351.check @@ -0,0 +1,13 @@ +./tests/patmat/t9351.scala:8: warning: match may not be exhaustive. +It would fail on the following input: _: A + a match { + ^ +./tests/patmat/t9351.scala:17: warning: match may not be exhaustive. +It would fail on the following input: (_, _), (_, None), (_, Some(_)) + (a, o) match { + ^ +./tests/patmat/t9351.scala:28: warning: match may not be exhaustive. +It would fail on the following input: (_, _) + (a, b) match { + ^ +three warnings found
\ No newline at end of file diff --git a/tests/patmat/t9351.scala b/tests/patmat/t9351.scala new file mode 100644 index 000000000..9b9bd4312 --- /dev/null +++ b/tests/patmat/t9351.scala @@ -0,0 +1,35 @@ +trait A {} +case object B extends A {} +case object C extends A {} + +class X { + def good = { + val a: A = B + a match { + case B => + case C => + } + } + + def bad = { + val a: A = B + val o: Option[Int] = None + (a, o) match { + case (B, None) => + case (B, Some(_)) => + case (C, None) => + case (C, Some(_)) => + } + } + + def alsoGood = { + val a: A = B + val b: A = C + (a, b) match { + case (B, B) => + case (B, C) => + case (C, B) => + case (C, C) => + } + } +} diff --git a/tests/patmat/t9398.check b/tests/patmat/t9398.check new file mode 100644 index 000000000..0efbf231d --- /dev/null +++ b/tests/patmat/t9398.check @@ -0,0 +1,5 @@ +./tests/patmat/t9398.scala:11: warning: match may not be exhaustive. +It would fail on the following input: CC(_, B2) + case CC(_, B) => () + ^ +one warning found diff --git a/tests/patmat/t9398.scala b/tests/patmat/t9398.scala new file mode 100644 index 000000000..6d4d6bd3b --- /dev/null +++ b/tests/patmat/t9398.scala @@ -0,0 +1,13 @@ +sealed abstract class TA +sealed abstract class TB extends TA +case object B extends TB +case object B2 extends TB + +case class CC(i: Int, tb: TB) + +object Test { + // Should warn that CC(_, B2) isn't matched + def foo: CC => Unit = { + case CC(_, B) => () + } +}
\ No newline at end of file diff --git a/tests/patmat/t9399.scala b/tests/patmat/t9399.scala new file mode 100644 index 000000000..89dbedd96 --- /dev/null +++ b/tests/patmat/t9399.scala @@ -0,0 +1,16 @@ +sealed abstract class TA +sealed abstract class TB extends TA +case object A extends TA +case object B extends TB + +sealed trait C +case class CTA(id: Int, da: TA) extends C +case class CTB(id: Int, da: TB) extends C + +object Test { + val test: C => Unit = { + case CTA(_, A) => + case CTA(_, B) => + case CTB(_, B) => + } +} diff --git a/tests/patmat/t9411a.scala b/tests/patmat/t9411a.scala new file mode 100644 index 000000000..d5264663e --- /dev/null +++ b/tests/patmat/t9411a.scala @@ -0,0 +1,27 @@ +object OhNoes { + + sealed trait F + sealed abstract class FA extends F + sealed abstract class FB extends F + + case object FA1 extends FA + case object FB1 extends FB + case object FB2 extends FB + + sealed trait G + case object G1 extends G + case object G2 extends G + + sealed trait H + case class H1(a: FB, b: G) extends H + case class H2(a: F) extends H + + val demo: H => Unit = { + case H1(FB1, G1) => + case H1(FB2, G2) => + case H2(_: FB) => + case H2(_: FA) => + case H1(FB1, G2) => + case H1(FB2, G1) => + } +} diff --git a/tests/patmat/t9411b.scala b/tests/patmat/t9411b.scala new file mode 100644 index 000000000..6888ba938 --- /dev/null +++ b/tests/patmat/t9411b.scala @@ -0,0 +1,36 @@ +object OhNoes { + + sealed trait F + sealed abstract class FA extends F + sealed abstract class FB extends F + + case object FA1 extends FA + case object FB1 extends FB + case object FB2 extends FB + + sealed trait G + case object G1 extends G + case object G2 extends G + + sealed trait H + case class H1(a: FB, b: G) extends H + case class H2(b: F) extends H + + val demo: H => Unit = { + case H1(FB1, G1) => + case H1(FB2, G2) => + case H2(_: FB) => + case H2(_: FA) => + case H1(FB1, G2) => + case H1(FB2, G1) => + } + + val demo2: H => Unit = { + case H2(_: FA) => + case H2(_: FB) => + case H1(FB1, G1) => + case H1(FB2, G1) => + case H1(FB1, G2) => + case H1(FB2, G2) => + } +} diff --git a/tests/patmat/t9573.check b/tests/patmat/t9573.check new file mode 100644 index 000000000..4ec379161 --- /dev/null +++ b/tests/patmat/t9573.check @@ -0,0 +1,5 @@ +./tests/patmat/t9573.scala:9: warning: match may not be exhaustive. +It would fail on the following input: Horse(_) + x match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t9573.scala b/tests/patmat/t9573.scala new file mode 100644 index 000000000..2a32c2599 --- /dev/null +++ b/tests/patmat/t9573.scala @@ -0,0 +1,13 @@ +class Foo { + + def foo = { + abstract sealed class Animal + case class Goat(age: Int) extends Animal + case class Horse(age: Int) extends Animal + + val x: Animal = Goat(1) + x match { + case Goat(_) => println("a goat") + } + } +}
\ No newline at end of file diff --git a/tests/patmat/t9630.scala b/tests/patmat/t9630.scala new file mode 100644 index 000000000..c846faa99 --- /dev/null +++ b/tests/patmat/t9630.scala @@ -0,0 +1,21 @@ +sealed trait OpError +sealed trait RequestErrorType +sealed trait ProcessingErrorType + +final case class InvalidEndpoint(reason: String) extends RequestErrorType +final case class InvalidParameters(reason: String) extends RequestErrorType + +final case class InvalidFormat(response: String) extends ProcessingErrorType +final case class EntityNotFound(id: Long) extends ProcessingErrorType + +final case class RequestError(errorType: RequestErrorType) extends OpError +final case class ProcessingError(errorType: ProcessingErrorType) extends OpError + +object Test{ + def printMatches(error: OpError): Unit = error match { + case RequestError(InvalidEndpoint(reason)) => //print something + case RequestError(InvalidParameters(reason)) => //print something + case ProcessingError(InvalidFormat(format)) => //print something + case ProcessingError(EntityNotFound(entityId)) => //print something + } +}
\ No newline at end of file diff --git a/tests/patmat/t9657.check b/tests/patmat/t9657.check new file mode 100644 index 000000000..d3e2ec73f --- /dev/null +++ b/tests/patmat/t9657.check @@ -0,0 +1,17 @@ +./tests/patmat/t9657.scala:29: warning: match may not be exhaustive. +It would fail on the following input: Bus(_) + def refuel2[P <: Petrol.type](vehicle: Vehicle {type A = P} ): Vehicle = vehicle match { + ^ +./tests/patmat/t9657.scala:38: warning: match may not be exhaustive. +It would fail on the following input: Bus(_) + def foo2(vehicle: Vehicle {type A <: Petrol.type} ): Vehicle = vehicle match { + ^ +./tests/patmat/t9657.scala:49: warning: match may not be exhaustive. +It would fail on the following input: Bus(_) + def bar2(vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + ^ +./tests/patmat/t9657.scala:58: warning: match may not be exhaustive. +It would fail on the following input: Bus(_) + def qux2[P <: Petrol.type](vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + ^ +four warnings found
\ No newline at end of file diff --git a/tests/patmat/t9657.scala b/tests/patmat/t9657.scala new file mode 100644 index 000000000..f9769574e --- /dev/null +++ b/tests/patmat/t9657.scala @@ -0,0 +1,62 @@ +sealed trait PowerSource + +case object Petrol extends PowerSource + +case object Pedal extends PowerSource + +sealed abstract class Vehicle { + type A <: PowerSource +} + +case object Bicycle extends Vehicle { + type A = Pedal.type +} + +case class Bus(fuel: Int) extends Vehicle { + type A = Petrol.type +} + +case class Car(fuel: Int) extends Vehicle { + type A = Petrol.type +} + +class Test { + def refuel[P <: Petrol.type](vehicle: Vehicle {type A = P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + case Bus(_) => Bus(100) + } + + def refuel2[P <: Petrol.type](vehicle: Vehicle {type A = P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + } + + def foo1(vehicle: Vehicle {type A <: Petrol.type} ): Vehicle = vehicle match { + case Car(_) => Car(100) + case Bus(_) => Bus(100) + } + + def foo2(vehicle: Vehicle {type A <: Petrol.type} ): Vehicle = vehicle match { + case Car(_) => Car(100) + } + + type P = Petrol.type + + def bar1(vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + case Bus(_) => Bus(100) + } + + def bar2(vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + } + + def qux1[P <: Petrol.type](vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + case Bus(_) => Bus(100) + } + + def qux2[P <: Petrol.type](vehicle: Vehicle {type A <: P} ): Vehicle = vehicle match { + case Car(_) => Car(100) + } + +} diff --git a/tests/patmat/t9672.check b/tests/patmat/t9672.check new file mode 100644 index 000000000..3284d1df1 --- /dev/null +++ b/tests/patmat/t9672.check @@ -0,0 +1,5 @@ +./tests/patmat/t9672.scala:22: warning: match may not be exhaustive. +It would fail on the following input: SimpleExpr.IntExpr(_) + def func(expr: Expr) = expr match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t9672.scala b/tests/patmat/t9672.scala new file mode 100644 index 000000000..fe068f3d5 --- /dev/null +++ b/tests/patmat/t9672.scala @@ -0,0 +1,28 @@ +trait Hierarchy { + sealed trait Expr +} +trait If { + this: Hierarchy => + case class If(cond: Expr, yes: Expr, no: Expr) extends Expr +} +trait Word { + this: Hierarchy => + case class Word(name: String) extends Expr +} +trait IntExpr { + this: Hierarchy => + case class IntExpr(value : Int) extends Expr +} + +object SimpleExpr extends Hierarchy with If with Word with IntExpr +//object OtherExpr extends Hierarchy with If with IntExpr + +object Demo extends App { + import SimpleExpr._ + def func(expr: Expr) = expr match { + case If(cond, yes, no) => cond + case Word(name) => name + // compiler should emit warning "missing case statement" + // emits the wrong warning "unreachable code" + } +}
\ No newline at end of file diff --git a/tests/patmat/t9677.check b/tests/patmat/t9677.check new file mode 100644 index 000000000..f1e1817cb --- /dev/null +++ b/tests/patmat/t9677.check @@ -0,0 +1,4 @@ +./tests/patmat/t9677.scala:20: warning: unreachable code + case path: A => println("Not root") + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t9677.scala b/tests/patmat/t9677.scala new file mode 100644 index 000000000..1e9b1df5e --- /dev/null +++ b/tests/patmat/t9677.scala @@ -0,0 +1,23 @@ +sealed abstract class Base + +sealed trait A extends Base + +object A { + + case object Root extends Base + + def apply(param: String): A = { + new A {} + } +} + +object ExhaustiveMatchWarning { + + def test: Unit = { + val b: Base = A("blabla") + b match { + case A.Root => println("Root") + case path: A => println("Not root") + } + } +}
\ No newline at end of file diff --git a/tests/patmat/t9779.check b/tests/patmat/t9779.check new file mode 100644 index 000000000..0e0d8d5f4 --- /dev/null +++ b/tests/patmat/t9779.check @@ -0,0 +1,5 @@ +./tests/patmat/t9779.scala:10: warning: match may not be exhaustive. +It would fail on the following input: _: a.Elem + private def toLuaValue(eX: a.Elem[_]): String = eX match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/t9779.scala b/tests/patmat/t9779.scala new file mode 100644 index 000000000..9c418b0b1 --- /dev/null +++ b/tests/patmat/t9779.scala @@ -0,0 +1,13 @@ +trait Elems { + sealed class Elem[A] extends Dummy + + val UnitElement: Elem[Unit] + + trait Dummy +} + +class BadMatch[A <: Elems](a: A) { + private def toLuaValue(eX: a.Elem[_]): String = eX match { + case a.UnitElement => "" // type mismatch + } +}
\ No newline at end of file diff --git a/tests/patmat/try.scala b/tests/patmat/try.scala new file mode 100644 index 000000000..d7df24ee0 --- /dev/null +++ b/tests/patmat/try.scala @@ -0,0 +1,5 @@ +object Test { + try 2/0 catch { + case e: Exception => + } +}
\ No newline at end of file diff --git a/tests/patmat/tuple.scala b/tests/patmat/tuple.scala new file mode 100644 index 000000000..f33a5cfec --- /dev/null +++ b/tests/patmat/tuple.scala @@ -0,0 +1,5 @@ +object Test { + (4, (4, 6)) match { + case (x, (y, z)) => true + } +}
\ No newline at end of file diff --git a/tests/patmat/virtpatmat_apply.check b/tests/patmat/virtpatmat_apply.check new file mode 100644 index 000000000..d10d82165 --- /dev/null +++ b/tests/patmat/virtpatmat_apply.check @@ -0,0 +1,5 @@ +./tests/patmat/virtpatmat_apply.scala:2: warning: match may not be exhaustive. +It would fail on the following input: List(_) + List(1, 2, 3) match { + ^ +one warning found
\ No newline at end of file diff --git a/tests/patmat/virtpatmat_apply.scala b/tests/patmat/virtpatmat_apply.scala new file mode 100644 index 000000000..646d15f90 --- /dev/null +++ b/tests/patmat/virtpatmat_apply.scala @@ -0,0 +1,7 @@ +object Test { + List(1, 2, 3) match { + case Nil => println("FAIL") + case x :: y :: xs if xs.length == 2 => println("FAIL") + case x :: y :: xs if xs.length == 1 => println("OK "+ y) + } +} diff --git a/tests/patmat/virtpatmat_exhaust_compound.check b/tests/patmat/virtpatmat_exhaust_compound.check new file mode 100644 index 000000000..72e034068 --- /dev/null +++ b/tests/patmat/virtpatmat_exhaust_compound.check @@ -0,0 +1,15 @@ +virtpatmat_exhaust_compound.scala:14: warning: match may not be exhaustive. +It would fail on the following inputs: O1, O2, O4 + a match { + ^ +virtpatmat_exhaust_compound.scala:18: warning: match may not be exhaustive. +It would fail on the following input: O4 + def t1(a: Product with Base with Base2) = a match { + ^ +virtpatmat_exhaust_compound.scala:22: warning: match may not be exhaustive. +It would fail on the following input: O2 + def t2(a: Product with Base { def foo: Int }) = a match { + ^ +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/tests/patmat/virtpatmat_exhaust_compound.scala.ignore b/tests/patmat/virtpatmat_exhaust_compound.scala.ignore new file mode 100644 index 000000000..4ff04dd06 --- /dev/null +++ b/tests/patmat/virtpatmat_exhaust_compound.scala.ignore @@ -0,0 +1,29 @@ +sealed trait Base +case object O1 extends Base +case object O2 extends Base { + def foo: Int = 0 +} + +sealed trait Base2 +case object O3 extends Base2 + +case object O4 extends Base with Base2 + +object Test { + val a /*: Product with Serializable with Base */ = if (true) O1 else O2 + a match { + case null => + } + + def t1(a: Product with Base with Base2) = a match { + case null => // O1..O3 should *not* be possible here + } + + def t2(a: Product with Base { def foo: Int }) = a match { + case null => // O2 in the domain + } + + def t3(a: Product with Base { def bar: Int }) = a match { + case null => // nothing in the domain + } +} diff --git a/tests/patmat/virtpatmat_reach_sealed_unsealed.check b/tests/patmat/virtpatmat_reach_sealed_unsealed.check new file mode 100644 index 000000000..ef5ec1a00 --- /dev/null +++ b/tests/patmat/virtpatmat_reach_sealed_unsealed.check @@ -0,0 +1,11 @@ +./tests/patmat/virtpatmat_reach_sealed_unsealed.scala:16: warning: match may not be exhaustive. +It would fail on the following input: false + (true: Boolean) match { case true => } // not exhaustive, but reachable + ^ +./tests/patmat/virtpatmat_reach_sealed_unsealed.scala:18: warning: unreachable code + (true: Boolean) match { case true => case false => case _ => } // exhaustive, last case is unreachable + ^ +./tests/patmat/virtpatmat_reach_sealed_unsealed.scala:19: warning: unreachable code + (true: Boolean) match { case true => case false => case _: Boolean => } // exhaustive, last case is unreachable + ^ +three warnings found diff --git a/tests/patmat/virtpatmat_reach_sealed_unsealed.scala b/tests/patmat/virtpatmat_reach_sealed_unsealed.scala new file mode 100644 index 000000000..13911dbd7 --- /dev/null +++ b/tests/patmat/virtpatmat_reach_sealed_unsealed.scala @@ -0,0 +1,21 @@ +sealed abstract class X +sealed case class A(x: Int) extends X + +// test reachability on mixed sealed / non-sealed matches +object Test extends App { + val B: X = A(0) + val C: X = A(1) + + // all cases are reachable and the match is exhaustive + (C: X) match { + case B => + case C => + case A(_) => + } + + (true: Boolean) match { case true => } // not exhaustive, but reachable + (true: Boolean) match { case true => case false => } // exhaustive, reachable + (true: Boolean) match { case true => case false => case _ => } // exhaustive, last case is unreachable + (true: Boolean) match { case true => case false => case _: Boolean => } // exhaustive, last case is unreachable + (true: Boolean) match { case true => case false => case _: Any => } // exhaustive, last case is unreachable +}
\ No newline at end of file |