From 3c3d2c8e29b7a6547242e94c824ccfcf7cb3a504 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 27 Aug 2020 13:57:19 +0100 Subject: [PATCH] Always check exhaustivity of custom extractors/guards --- .../tools/nsc/settings/ScalaSettings.scala | 2 - .../nsc/transform/patmat/MatchAnalysis.scala | 8 +- test/files/neg/t5365.check | 24 +++- test/files/neg/t5365b.scala | 2 +- test/files/neg/t5365c.scala | 2 +- test/files/neg/t5365d.scala | 2 +- test/files/neg/t5365e.check | 12 +- test/files/neg/t5365e.scala | 8 +- test/files/run/lisp.check | 64 ++++++++++ test/files/run/lists-run.check | 4 + test/files/run/macro-expand-unapply-a.check | 8 ++ test/files/run/matchonstream.check | 4 + test/files/run/patmat-behavior.check | 120 ++++++++++++++++++ .../files/run/patmat-mix-case-extractor.check | 4 + test/files/run/patmatnew.check | 16 +++ test/files/run/sd167.check | 4 + test/files/run/t5903a.check | 4 + test/files/run/t6541.scala | 1 + test/files/run/t7871.check | 4 + test/files/run/t9003.check | 20 +++ test/files/run/t9567c.check | 12 ++ test/files/run/unapply.check | 4 + test/files/run/virtpatmat_stringinterp.check | 4 + test/files/run/virtpatmat_unapplyprod.check | 8 ++ test/files/run/virtpatmat_unapplyseq.check | 6 +- 25 files changed, 322 insertions(+), 25 deletions(-) create mode 100644 test/files/run/lists-run.check create mode 100644 test/files/run/t9003.check create mode 100644 test/files/run/t9567c.check diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index af40f94ba3fa..43d417b5d4f8 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -174,8 +174,6 @@ trait ScalaSettings extends AbsScalaSettings def isAtLeastJunit = isTruthy || XmixinForceForwarders.value == "junit" } - val XstrictPatmatAnalysis = BooleanSetting ("-Xstrict-patmat-analysis", "Assume pattern guards are false for the purposes of exhaustivity analysis") - // XML parsing options object XxmlSettings extends MultiChoiceEnumeration { val coalescing = Choice("coalescing", "Convert PCData to Text and coalesce sibling nodes") diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 99e6763c1810..15df431f9a21 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -529,7 +529,6 @@ trait MatchAnalysis extends MatchApproximation { // - back off (to avoid crying exhaustive too often) in unhandled cases val start = if (StatisticsStatics.areSomeColdStatsEnabled) statistics.startTimer(statistics.patmatAnaExhaust) else null var backoff = false - val strict = settings.XstrictPatmatAnalysis.value val approx = new TreeMakersToProps(prevBinder) val symbolicCases = approx.approximateMatch(cases, approx.onUnknown { tm => @@ -538,8 +537,9 @@ trait MatchAnalysis extends MatchApproximation { case ExtractorTreeMaker(_, _, _) | ProductExtractorTreeMaker(_, _) | GuardTreeMaker(_) => - if (strict) False else True - case _ => // debug.patmat("backing off due to "+ tm) + False + case _ => + debug.patmat("backing off due to "+ tm) backoff = true False }) @@ -904,7 +904,7 @@ trait MatchAnalysis extends MatchApproximation { // then we can safely ignore these counter examples since we will eventually encounter // both counter examples separately case _ if inSameDomain => - if (settings.XstrictPatmatAnalysis.value) Some(WildcardExample) else None + Some(WildcardExample) // not a valid counter-example, possibly since we have a definite type but there was a field mismatch // TODO: improve reasoning -- in the mean time, a false negative is better than an annoying false positive diff --git a/test/files/neg/t5365.check b/test/files/neg/t5365.check index fcae3346799e..ab18ea18cb27 100644 --- a/test/files/neg/t5365.check +++ b/test/files/neg/t5365.check @@ -1,15 +1,31 @@ t5365.scala:3: warning: match may not be exhaustive. -It would fail on the following input: None +It would fail on the following inputs: None, Some(_) def nonExhautiveIfWeAssumeGuardsTrueOrFalse(x: Option[Int]): Int = x match { ^ +t5365.scala:7: warning: match may not be exhaustive. +It would fail on the following input: Some(_) + def nonExhautiveIfWeAssumeGuardsFalse(x: Option[Int]): Int = x match { + ^ +t5365.scala:12: warning: match may not be exhaustive. +It would fail on the following input: Some(_) + def inverseGuards(x: Option[Int]): Int = x match { + ^ t5365.scala:18: warning: match may not be exhaustive. -It would fail on the following input: None +It would fail on the following inputs: None, Some(_) def extractor(x: Option[Int]) = x match { ^ t5365.scala:21: warning: match may not be exhaustive. -It would fail on the following input: None +It would fail on the following inputs: None, Some(_) def repeatedExtractor(x: Option[Int]) = x match { ^ +t5365.scala:24: warning: match may not be exhaustive. +It would fail on the following input: Some(_) + def extractorStrict(x: Option[Int]) = x match { + ^ +t5365.scala:28: warning: match may not be exhaustive. +It would fail on the following input: Some(_) + def repeatedExtractorStrict(x: Option[Int]) = x match { + ^ error: No warnings can be incurred under -Xfatal-warnings. -three warnings found +7 warnings found one error found diff --git a/test/files/neg/t5365b.scala b/test/files/neg/t5365b.scala index 7dd3ef4cdee6..25a6dcc8cf67 100644 --- a/test/files/neg/t5365b.scala +++ b/test/files/neg/t5365b.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings -Xstrict-patmat-analysis +// scalac: -Xfatal-warnings class C { def nonExhautiveIfWeAssumeGuardsTrueOrFalse(x: Option[Int]): Int = x match { case Some(n) if n % 2 == 0 => n diff --git a/test/files/neg/t5365c.scala b/test/files/neg/t5365c.scala index fc8deabc86f0..d79cd905c0d4 100644 --- a/test/files/neg/t5365c.scala +++ b/test/files/neg/t5365c.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings -Xstrict-patmat-analysis -Xlint:strict-unsealed-patmat +// scalac: -Xfatal-warnings -Xlint:strict-unsealed-patmat object C { trait Z final case class Q(i: Int) extends Z diff --git a/test/files/neg/t5365d.scala b/test/files/neg/t5365d.scala index 31ea5404f6cd..eab29e7ecead 100644 --- a/test/files/neg/t5365d.scala +++ b/test/files/neg/t5365d.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings -Xstrict-patmat-analysis +// scalac: -Xfatal-warnings object D { sealed trait T final case class C(i: Int) extends T diff --git a/test/files/neg/t5365e.check b/test/files/neg/t5365e.check index 315905220374..a4f2ceed14a4 100644 --- a/test/files/neg/t5365e.check +++ b/test/files/neg/t5365e.check @@ -1,13 +1,13 @@ t5365e.scala:8: warning: match may not be exhaustive. -It would fail on the following input: Bar(_) +It would fail on the following inputs: Bar(_), Foo(_) def f0(x: Exh) = x match { case Foo() => () } // don't back off ^ t5365e.scala:9: warning: match may not be exhaustive. -It would fail on the following input: Bar(_) +It would fail on the following inputs: Bar(_), Foo(_) def f1(x: Exh) = x match { case Foo(x) => x } // don't back off ^ t5365e.scala:10: warning: match may not be exhaustive. -It would fail on the following input: Bar(_) +It would fail on the following inputs: Bar(_), Foo(_) def f2(x: Exh) = x match { case Foo(x, y) => x + y } // don't back off ^ t5365e.scala:11: warning: match may not be exhaustive. @@ -18,6 +18,10 @@ t5365e.scala:12: warning: match may not be exhaustive. It would fail on the following input: Foo(_) def b1(x: Exh) = x match { case Bar(x) => x } // inexhaustive ^ +t5365e.scala:13: warning: match may not be exhaustive. +It would fail on the following input: Foo(_) + def fb(x: Exh) = x match { case Foo(x) => x case Bar(x) => x } // pessimistically inexhaustive + ^ error: No warnings can be incurred under -Xfatal-warnings. -5 warnings found +6 warnings found one error found diff --git a/test/files/neg/t5365e.scala b/test/files/neg/t5365e.scala index ae26ab8ed5c5..5975587cbf94 100644 --- a/test/files/neg/t5365e.scala +++ b/test/files/neg/t5365e.scala @@ -10,11 +10,5 @@ class Main { def f2(x: Exh) = x match { case Foo(x, y) => x + y } // don't back off def fX(x: Exh) = x match { case Foo(xs @ _*) => xs } // don't back off def b1(x: Exh) = x match { case Bar(x) => x } // inexhaustive - def fb(x: Exh) = x match { case Foo(x) => x case Bar(x) => x } // optimistically exhaustive - // ^ under -Xstrict-patmat-analysis pessimistically approximates case Foo(x) as inexhaustive: - // test/files/neg/t5365e.scala:12: warning: match may not be exhaustive. - // It would fail on the following input: Foo(_) - // def fb(x: Exh) = x match { case Foo(x) => x case Bar(x) => x } // optimistically exhaustive - // ^ - // ... and the counter-example needs work -.- ... + def fb(x: Exh) = x match { case Foo(x) => x case Bar(x) => x } // pessimistically inexhaustive } diff --git a/test/files/run/lisp.check b/test/files/run/lisp.check index 64053f26d0b3..01284a5f5468 100644 --- a/test/files/run/lisp.check +++ b/test/files/run/lisp.check @@ -1,3 +1,67 @@ +lisp.scala:211: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("=", FUN({ + ^ +lisp.scala:214: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("+", FUN({ + ^ +lisp.scala:217: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("-", FUN({ + ^ +lisp.scala:219: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("*", FUN({ + ^ +lisp.scala:221: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("/", FUN({ + ^ +lisp.scala:223: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("car", FUN({ + ^ +lisp.scala:225: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("cdr", FUN({ + ^ +lisp.scala:230: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("cons", FUN({ + ^ +lisp.scala:402: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("=", Lambda{ + ^ +lisp.scala:404: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("+", Lambda{ + ^ +lisp.scala:407: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("-", Lambda{ + ^ +lisp.scala:409: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("*", Lambda{ + ^ +lisp.scala:411: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("/", Lambda{ + ^ +lisp.scala:414: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("cons", Lambda{ + ^ +lisp.scala:416: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("car", Lambda{ + ^ +lisp.scala:418: warning: match may not be exhaustive. +It would fail on the following input: _ + .extend("cdr", Lambda{ + ^ (lambda (x) (+ (* x x) 1)) (lambda (x) (+ (* x x) 1)) diff --git a/test/files/run/lists-run.check b/test/files/run/lists-run.check new file mode 100644 index 000000000000..163e64900075 --- /dev/null +++ b/test/files/run/lists-run.check @@ -0,0 +1,4 @@ +lists-run.scala:177: warning: match may not be exhaustive. +It would fail on the following input: List((x: String forSome x not in "foo")) + def show(xs: List[String]) = xs match { + ^ diff --git a/test/files/run/macro-expand-unapply-a.check b/test/files/run/macro-expand-unapply-a.check index 7c2976e51e03..b5688e06de60 100644 --- a/test/files/run/macro-expand-unapply-a.check +++ b/test/files/run/macro-expand-unapply-a.check @@ -1,2 +1,10 @@ +Test_2.scala:5: warning: match may not be exhaustive. +It would fail on the following input: _ + List(1, 2) match { case UnapplyMacro(x, y) => println((x, y)) } + ^ +Test_2.scala:6: warning: match may not be exhaustive. +It would fail on the following input: _ + List(1, 2, 3) match { case UnapplyMacro(x, y, z) => println((x, y, z)) } + ^ (1,2) (1,2,3) diff --git a/test/files/run/matchonstream.check b/test/files/run/matchonstream.check index 3dc3aa5164a7..955bc188a82e 100644 --- a/test/files/run/matchonstream.check +++ b/test/files/run/matchonstream.check @@ -1 +1,5 @@ +matchonstream.scala:2: warning: match may not be exhaustive. +It would fail on the following input: _ + Stream.from(1) match { case Stream(1, 2, x @_*) => println("It worked!") } + ^ It worked! diff --git a/test/files/run/patmat-behavior.check b/test/files/run/patmat-behavior.check index 273a1434fbd3..8ee224ec0cf7 100644 --- a/test/files/run/patmat-behavior.check +++ b/test/files/run/patmat-behavior.check @@ -88,3 +88,123 @@ patmat-behavior.scala:87: warning: fruitless type test: a value of type s.C21[A] patmat-behavior.scala:87: warning: fruitless type test: a value of type s.C21[A] cannot also be a s.C11[A] def gd6[A](x: C21[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } ^ +patmat-behavior.scala:43: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb1[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:44: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb2[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:45: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb3[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:46: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb4[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:47: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb5[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:48: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb6[A](x: C[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:50: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc1[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:51: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc2[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:52: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc3[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:53: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc4[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:54: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc5[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:55: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc6[A](x: C[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:68: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb1[A](x: C00[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:69: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb2[A](x: C10[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:70: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb3[A](x: C20[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:71: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb4[A](x: C01[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:72: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb5[A](x: C11[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:73: warning: match may not be exhaustive. +It would fail on the following input: _ + def gb6[A](x: C21[A]) = x match { case E00() => ??? ; case E10(x) => x ; case E20(x, y) => x ; case E01(xs @ _*) => xs.head ; case E11(x, ys @ _*) => x ; case E21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:75: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc1[A](x: C00[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:76: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc2[A](x: C10[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:77: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc3[A](x: C20[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:78: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc4[A](x: C01[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:79: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc5[A](x: C11[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:80: warning: match may not be exhaustive. +It would fail on the following input: _ + def gc6[A](x: C21[A]) = x match { case F00() => ??? ; case F10(x) => x ; case F20(x, y) => x ; case F01(xs @ _*) => xs.head ; case F11(x, ys @ _*) => x ; case F21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:82: warning: match may not be exhaustive. +It would fail on the following input: C00() + def gd1[A](x: C00[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:83: warning: match may not be exhaustive. +It would fail on the following input: C10(_) + def gd2[A](x: C10[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:84: warning: match may not be exhaustive. +It would fail on the following input: C20(_, _) + def gd3[A](x: C20[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:85: warning: match may not be exhaustive. +It would fail on the following input: C01(_) + def gd4[A](x: C01[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:86: warning: match may not be exhaustive. +It would fail on the following input: C11(_, _) + def gd5[A](x: C11[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ +patmat-behavior.scala:87: warning: match may not be exhaustive. +It would fail on the following input: C21(_, _, _) + def gd6[A](x: C21[A]) = x match { case G00() => ??? ; case G10(x) => x ; case G20(x, y) => x ; case G01(xs @ _*) => xs.head ; case G11(x, ys @ _*) => x ; case G21(x, y, zs @ _*) => x } + ^ diff --git a/test/files/run/patmat-mix-case-extractor.check b/test/files/run/patmat-mix-case-extractor.check index a6e1bd23dfee..3749c7ddc03d 100644 --- a/test/files/run/patmat-mix-case-extractor.check +++ b/test/files/run/patmat-mix-case-extractor.check @@ -1,3 +1,7 @@ +patmat-mix-case-extractor.scala:72: warning: match may not be exhaustive. +It would fail on the following input: _ + def f3(x: CaseSeq) = x match { + ^ -1 6 4 diff --git a/test/files/run/patmatnew.check b/test/files/run/patmatnew.check index 72f4289b9211..ca4ddefd4dda 100644 --- a/test/files/run/patmatnew.check +++ b/test/files/run/patmatnew.check @@ -1,6 +1,22 @@ patmatnew.scala:670: warning: This catches all Throwables. If this is really intended, use `case e : Throwable` to clear this warning. case e => { ^ +patmatnew.scala:175: warning: match may not be exhaustive. +It would fail on the following input: _ + def doMatch2(xs: List[String]): List[String] = xs match { + ^ +patmatnew.scala:277: warning: match may not be exhaustive. +It would fail on the following input: _ + def doMatch1(xs: List[Char]) = xs match { + ^ +patmatnew.scala:280: warning: match may not be exhaustive. +It would fail on the following input: _ + def doMatch2(xs: List[Char]) = xs match { + ^ +patmatnew.scala:315: warning: match may not be exhaustive. +It would fail on the following input: Cons() + stream match { + ^ patmatnew.scala:489: warning: unreachable code case _ if false => ^ diff --git a/test/files/run/sd167.check b/test/files/run/sd167.check index 587be6b4c3f9..44ab5c95852e 100644 --- a/test/files/run/sd167.check +++ b/test/files/run/sd167.check @@ -1 +1,5 @@ +sd167.scala:6: warning: match may not be exhaustive. +It would fail on the following input: _ + Some(1) match { case x"${a}" => } // used to convert to `case Some(a) =>` and omit side effects + ^ x diff --git a/test/files/run/t5903a.check b/test/files/run/t5903a.check index ce6efd812d76..97a622fec15d 100644 --- a/test/files/run/t5903a.check +++ b/test/files/run/t5903a.check @@ -1 +1,5 @@ +Test_2.scala:4: warning: match may not be exhaustive. +It would fail on the following input: _ + SomeTree match { + ^ (SomeTree,SomeTree) diff --git a/test/files/run/t6541.scala b/test/files/run/t6541.scala index 05375b0c3de2..ccc5b3e396dd 100644 --- a/test/files/run/t6541.scala +++ b/test/files/run/t6541.scala @@ -14,6 +14,7 @@ object Test extends App { def f2(d: D) = d match { case D(a, b1, b2) => () + case _ => ??? } def f3(e: E) = e match { diff --git a/test/files/run/t7871.check b/test/files/run/t7871.check index ce6efd812d76..3561de674a57 100644 --- a/test/files/run/t7871.check +++ b/test/files/run/t7871.check @@ -1 +1,5 @@ +Test_2.scala:3: warning: match may not be exhaustive. +It would fail on the following input: _ + SomeTree match { + ^ (SomeTree,SomeTree) diff --git a/test/files/run/t9003.check b/test/files/run/t9003.check new file mode 100644 index 000000000000..2ece1cff904c --- /dev/null +++ b/test/files/run/t9003.check @@ -0,0 +1,20 @@ +t9003.scala:32: warning: match may not be exhaustive. +It would fail on the following input: _ + Single match { + ^ +t9003.scala:38: warning: match may not be exhaustive. +It would fail on the following input: _ + Product match { + ^ +t9003.scala:44: warning: match may not be exhaustive. +It would fail on the following input: _ + Sequence match { + ^ +t9003.scala:51: warning: match may not be exhaustive. +It would fail on the following input: _ + Sequence match { + ^ +t9003.scala:66: warning: match may not be exhaustive. +It would fail on the following input: _ + CaseSequence(buffer1: _*) match { + ^ diff --git a/test/files/run/t9567c.check b/test/files/run/t9567c.check new file mode 100644 index 000000000000..f377e12e5585 --- /dev/null +++ b/test/files/run/t9567c.check @@ -0,0 +1,12 @@ +t9567c.scala:7: warning: match may not be exhaustive. +It would fail on the following input: _ + CaseSequenceTopLevel(buffer1: _*) match { + ^ +t9567c.scala:15: warning: match may not be exhaustive. +It would fail on the following input: _ + CaseSequence(buffer2: _*) match { + ^ +t9567c.scala:23: warning: match may not be exhaustive. +It would fail on the following input: _ + CaseSequenceWithVar("", buffer3: _*) match { + ^ diff --git a/test/files/run/unapply.check b/test/files/run/unapply.check index 847e3b381e00..817809baf14a 100644 --- a/test/files/run/unapply.check +++ b/test/files/run/unapply.check @@ -1,3 +1,7 @@ +unapply.scala:97: warning: match may not be exhaustive. +It would fail on the following input: Cons() + stream match { + ^ unapply.scala:57: warning: comparing values of types Null and Null using `==' will always yield true assert(doMatch2(b) == null) ^ diff --git a/test/files/run/virtpatmat_stringinterp.check b/test/files/run/virtpatmat_stringinterp.check index 7927f4f2d95a..5225b8569b4e 100644 --- a/test/files/run/virtpatmat_stringinterp.check +++ b/test/files/run/virtpatmat_stringinterp.check @@ -1 +1,5 @@ +virtpatmat_stringinterp.scala:16: warning: match may not be exhaustive. +It would fail on the following input: _ + x match { case xml"""""" => println(a) } + ^ Node(1) diff --git a/test/files/run/virtpatmat_unapplyprod.check b/test/files/run/virtpatmat_unapplyprod.check index 12d844f02ee6..99e5a6240e41 100644 --- a/test/files/run/virtpatmat_unapplyprod.check +++ b/test/files/run/virtpatmat_unapplyprod.check @@ -1,3 +1,11 @@ +virtpatmat_unapplyprod.scala:11: warning: match may not be exhaustive. +It would fail on the following input: _ + FooSeq(2, "3") match { + ^ +virtpatmat_unapplyprod.scala:15: warning: match may not be exhaustive. +It would fail on the following input: _ + FooSeq(2, "3", true, false, true) match { + ^ virtpatmat_unapplyprod.scala:20: warning: match may not be exhaustive. It would fail on the following inputs: FooSeq((x: Int forSome x not in 1), "a", _), FooSeq((x: Int forSome x not in 1), (x: String forSome x not in "a"), _), FooSeq(1, (x: String forSome x not in "a"), _) FooSeq(1, "a", true, false, true) match { diff --git a/test/files/run/virtpatmat_unapplyseq.check b/test/files/run/virtpatmat_unapplyseq.check index 62f9457511f8..ad34e6d0d330 100644 --- a/test/files/run/virtpatmat_unapplyseq.check +++ b/test/files/run/virtpatmat_unapplyseq.check @@ -1 +1,5 @@ -6 \ No newline at end of file +virtpatmat_unapplyseq.scala:3: warning: match may not be exhaustive. +It would fail on the following input: _ + List(1,2,3) match { + ^ +6