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

Spurious exhaustivity warning using an irrefutable unapply with a singleton type #13110

Closed
SrTobi opened this issue Jul 19, 2021 · 3 comments · Fixed by #13137
Closed

Spurious exhaustivity warning using an irrefutable unapply with a singleton type #13110

SrTobi opened this issue Jul 19, 2021 · 3 comments · Fixed by #13137

Comments

@SrTobi
Copy link
Contributor

SrTobi commented Jul 19, 2021

reproduction steps

minimized code:

object Test {
  sealed trait Base
  class Blub extends Base
  object Blub {
    def unapply(blub: Blub): Some[(Int, blub.type)] =
      Some(1 -> blub)
  }

  (null: Base) match {
    case Blub(i, x) => println(i)
  }
}

problem

Expect everything to compile without warnings, but gives

match may not be exhaustive.

It would fail on pattern case: Blub(_, _)

  (null: Base) match {

If the dependent type is removed or (null: Blub) used, the warning will go away

@dwijnand dwijnand self-assigned this Jul 20, 2021
@dwijnand dwijnand changed the title Exhaustiveness check does not work with irrefutable unapply involving dependend types Exhaustiveness check does not work with irrefutable unapply involving dependent types Jul 22, 2021
@dwijnand
Copy link
Member

To add further proof (not that it's needed IMO), I think it's obviously a false positive when:

  (null: Base) match {
    case b: Blub => b match {
      case Blub(i, x) => println(i)
    }
  }

doesn't give the warning.

@dwijnand
Copy link
Member

Hmm, maybe not good proof, as that doesn't warn because Blub isn't sealed... 🙄 When marked as sealed class Blub that version warns again. 🤔

@dwijnand
Copy link
Member

Here's some tracing output:

exhaustivity: selTyp = Test.Base
exhaustivity: pat=Test.Blub(i @ _, x @ _):Test.Blub ====> space=Blub(_{Int}, _{(?1 : Test.Blub)})
exhaustivity:     selSpace = _: Base
exhaustivity: patternSpace = Blub(_{Int}, _{(?1 : Test.Blub)})
==> _: Base - Blub(_{Int}, _{(?1 : Test.Blub)})?
...
signature of Test.Blub.unapply ----> [Int, Test.Blub]
        ==> Blub(_{Int}, _{Blub}) - Blub(_{Int}, _{(?1 : Test.Blub)})?
...
          ==> _{Blub} - _{(?1 : Test.Blub)}?
...
          <== _{Blub} - _{(?1 : Test.Blub)} = _{Blub}

Looks to me like the way patterns are projected to spaces captures the dependent type, while the reading of the unappy signature doesn't, so they don't cancel out.

@dwijnand dwijnand changed the title Exhaustiveness check does not work with irrefutable unapply involving dependent types Spurious exhaustivity warning using an irrefutable unapply with a singleton type Jul 26, 2021
@Kordyjan Kordyjan added this to the 3.1.0 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.

3 participants