Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern-matcher fails to emit exhaustiveness warning #9398

Closed
scabug opened this issue Jul 14, 2015 · 8 comments
Closed

Pattern-matcher fails to emit exhaustiveness warning #9398

scabug opened this issue Jul 14, 2015 · 8 comments
Assignees
Labels
Milestone

Comments

@scabug
Copy link

scabug commented Jul 14, 2015

The following snippet should produce a warning that CC(_, B2) isn't matched.

  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)

  // Should warn that CC(_, B2) isn't matched
  val test: CC => Unit = {
    case CC(_, B) => ()
  }
@scabug
Copy link
Author

scabug commented Jul 14, 2015

Imported From: https://issues.scala-lang.org/browse/SI-9398?orig=1
Reporter: David Barri (japgolly)
Affected Versions: 2.11.7

@scabug
Copy link
Author

scabug commented Jan 25, 2016

@retronym said:
No exhaustiveness error is expected here unless you mark the case class CC as final.

However, even with that change to the test case, the warning is not emitted. I have a patch in https://github.com/scala/scala/compare/2.12.x...retronym:ticket/9630?expand=1 that fixes that problem, I'll add that to the list of patmat improvements that I'll discuss with @adriaanm next week.

@scabug
Copy link
Author

scabug commented Jan 26, 2016

@paulp said:
What is the perceived relevance of CC being final? Is it another secret handshake issued by final, like "inline this value" or "don't give this nested case class an outer pointer" but in this case "check me for exhaustiveness" ? Is it specified?

@scabug
Copy link
Author

scabug commented Jan 26, 2016

@retronym said:
If the type of the scrutinee is not (effectively) sealed, exhaustiveness warnings aren't issued.

scala> def foo(a: AnyRef) = a match { case _: String => }
foo: (a: AnyRef)Unit

The code that deems this "uncheckable" for exhaustivity is: https://github.com/scala/scala/blob/v2.11.6/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala#L203-L213

I have a feeling that we might have carried this restricted checking across from the 2.9 era pattern matcher. I say this after comparing the analysis of a related match from 2.9 and 2.10:

scala> def foo(a: AnyRef) = Option(a) match { case Some(_: String) => case None => }; scala.util.Properties.releaseVersion
foo: (a: AnyRef)Unit
res10: Option[String] = Some(2.9.2)
scala> def foo(a: AnyRef) = Option(a) match { case Some(_: String) => case None => }; scala.util.Properties.releaseVersion
<console>:7: warning: match may not be exhaustive.
It would fail on the following input: Some((x: AnyRef forSome x not in String))
              def foo(a: AnyRef) = Option(a) match { case Some(_: String) => case None => };;
                                         ^
foo: (a: AnyRef)Unit
res0: Option[String] = Some(2.10.4)

So given that the new pattern matcher has the ability to articulate the counter examples, we might be able to turn on the analysis for all matches.

I will try to lift this restriction and see how the newly issued warnings distribute between useful and spurious.

A related change would be to approximate guards and extractors as always-false for the purposes of exhaustivity (currently they disable exhaustivity).

@scabug
Copy link
Author

scabug commented Jan 27, 2016

@paulp said:
The scrutinee is a CC and the pattern match is a CC. That ought to make it equivalent to a match on the case fields, which does warn. CC should be considered effectively sealed here even with no modifiers! It's a one element ADT.

  val test2: (Int, TB) => Unit = {
    case (_, B) => ()
  }
  // a.scala:14: warning: match may not be exhaustive.
  // It would fail on the following input: (_, B2)
  //   val test2: (Int, TB) => Unit = {
  //                                  ^
  // one warning found

@scabug
Copy link
Author

scabug commented Jan 27, 2016

@retronym said (edited on Jan 27, 2016 1:11:16 AM UTC):
Stricter warning: scala/scala@e5e93dd

... and the changes to the standard library to address the warnings: scala/scala@4954adc

@scabug
Copy link
Author

scabug commented Jan 27, 2016

@retronym said:
Turning exhaustiveness warning on in general is pretty noisy. Perhaps it could be made available with a -Xstrict-patmat-analysis.

So I agree with you: treating case classes as one element ADTs seems like a useful improvement.

@scabug
Copy link
Author

scabug commented Jan 27, 2016

@retronym said:
scala/scala#4919

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants