Skip to content

No warning is triggered for non-exhaustive pattern matching on case class field #12337

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

Closed
kevin-lee opened this issue May 5, 2021 · 6 comments · Fixed by #12377
Closed

No warning is triggered for non-exhaustive pattern matching on case class field #12337

kevin-lee opened this issue May 5, 2021 · 6 comments · Fixed by #12377

Comments

@kevin-lee
Copy link
Contributor

kevin-lee commented May 5, 2021

Compiler version

3.0.0-RC3 from print scalaVersion on sbt console.

Minimized code

sealed trait Status
object Status {
  case object Active   extends Status
  case object Inactive extends Status
}

final case class Foo(status: Status)
def bar(user: Foo): Unit = user match {
  case Foo(Status.Active) =>
    println("active")
    // no compile-time warning for missing Status.Inactive case
}

scalacOptions has

List(
  "-unchecked",
  "-deprecation",
  "-feature",
  "-Xfatal-warnings"
)

NOTE:

  • Replacing the Status above with the enum like below doesn't make any difference.

    enum Status {
      case Active
      case Inactive
    }
  • final case class (i.e. final case class Foo(status: Status)) makes no difference.

Output

It compiles without any warning or error even with -Xfatal-warnings, and it results in the following runtime error.

[error] (run-main-1) scala.MatchError: Foo(Inactive) (of class kevinlee.Example1$Foo)
[error] scala.MatchError: Foo(Inactive) (of class kevinlee.Example1$Foo)
...

Expectation

The compile-time warning like

match may not be exhaustive.
It would fail on the following input: Foo(Inactive)
    def bar(user: Foo): Unit = user match {

(or the compile-time error with "-Xfatal-warnings" compiler option)

@kevin-lee kevin-lee changed the title No warning is trigger for non-exhaustive pattern matching on case class field No warning is triggered for non-exhaustive pattern matching on case class field May 5, 2021
@liufengyun
Copy link
Contributor

liufengyun commented May 5, 2021

Exhaustivity check is not triggered since Foo is not sealed.

Changing final case class Foo to sealed case class Foo will get the warning:

sealed trait Status
object Status {
  case object Active   extends Status
  case object Inactive extends Status
}

sealed case class Foo(status: Status)
def bar(user: Foo): Unit = user match {
  case Foo(Status.Active) =>
    println("active")
    // no compile-time warning for missing Status.Inactive case
}
-- [E029] Pattern Match Exhaustivity Warning: examples/i12337.scala:8:27 -------
8 |def bar(user: Foo): Unit = user match {
  |                           ^^^^
  |                           match may not be exhaustive.
  |
  |                           It would fail on pattern case: Foo(Inactive)

@kevin-lee
Copy link
Contributor Author

@liufengyun Is it a changed behavior in Scala 3? The exactly the same code as mine in Scala 2 triggers non-exhaustive warning.

@liufengyun
Copy link
Contributor

@liufengyun Is it a changed behavior in Scala 3? The exactly the same code as mine in Scala 2 triggers non-exhaustive warning.

I don't think it's changed intentionally. It's just not well specified whether we should perform more checks in the absence of sealed. Given that it's supported in Scala 2, we could make Scala 3 to align with Scala 2 behavior.

@kevin-lee
Copy link
Contributor Author

kevin-lee commented May 5, 2021

@liufengyun Here is the same code in Scala 2.13.5. As you can see, the non-exhaustive warning is triggered.
https://scastie.scala-lang.org/AXKSl4K5S26cPjTE8b1kdw
https://scastie.scala-lang.org/KoU8DeZvTuKMlTfHFmHYeg (updated with non-final case class)

@som-snytt
Copy link
Contributor

final is also not required to see the warning in Scala 2. All that is required is that it walk like a duck.

@kevin-lee
Copy link
Contributor Author

@som-snytt Thanks. Yeah I forgot to mention that it triggers the warning in Scala 2 without final.
I probably shouldn't have put final there as it may cause confusion. I'll fix the example code. Thanks @som-snytt.

liufengyun added a commit to dotty-staging/dotty that referenced this issue May 7, 2021
…kable components

This aligns with Scala 2 behavior.
liufengyun added a commit that referenced this issue May 11, 2021
Fix #12337: Enable exhaustivity check for case classes with checkable components
@Kordyjan Kordyjan added this to the 3.0.1 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants