-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 match on GADT not recognizing case as impossible (regression from Scala 2) #12756
Comments
/cc @liufengyun could you remind me, did you end up adding support for GADT-aware exhaustivity checks? |
We do have some support by checking the counter-examples. But I don't think it's bullet-proof. For the example above, it's exhaustive, because |
@liufengyun FWIW this is a simplification of an example where there were multiple cases, some of which matches |
Any news on where this is on the roadmap? This is a blocker for me to upgrade to Scala 3. |
@Kazark I'll see about taking a look. Fengyun's comment suggest that a fix might be relatively simple. |
That Scala 2 error isn't an exhaustivity error, it's a typer error, because the match doesn't type. And I think it's right (or, rather, I can't think why Scala 3 thinks that's wrong), so I think the fix is in typing the case. |
SLS 8.5 states unambiguously that the pattern matching anonymous function desugars as follows: def whatthe[A, B]: Foo[A=>B] => Unit = new (Foo[A => B] => Unit) {
def apply(x: Foo[A => B]): Unit = x match { case Bar(_) => () }
} Scala 2 and Scala 3 are both consistent about handling the sugary and desugared versions the same (Scala 2 same error in both cases, Scala 3 no error in both cases). So we can disregard the pattern-matching-anonymous-function aspect of this and deal directly with the raw pattern match. We can also minimize it further to just: def whatthe[A, B](x: Foo[A => B]): Unit =
x match { case Bar(_) => () } again, Scala 2 gives a type error, Scala 3 accepts it. And note that Scala 2 isn't only rejecting the code because there's a single case. It still rejects it even if you put a catchall case in: def whatthe[A, B](x: Foo[A => B]): Unit =
x match { case Bar(_) => (); case _ => () } |
The minimized form is governed by SLS 8.4 (Pattern Matching Expressions), which states: Here the pattern type doesn't conform either to (I went down sort of a mental garden path of thinking this ought to be just an unreachable warning, but I was forgetting that "unreachable" refers primarily to a clause being unreachable in reference to previous clauses which have caused a following clause to become impossible to reach.) |
Minimized even further: def whatthe(x: Foo[Int]): Unit =
x match { case Bar(_) => () } No additional type parameters, no So this bug is really quite fundamental. (Even Scala 2.7 issues an error in this case; I looked in the Scala 2 history and the code for this seems to go all the way back to the initial commit of SOCOS, and perhaps because it's so old, there's no test coverage to speak of.) |
in
First, this ("ignore whether...") seems like a peculiar choice, because if we've detected early that the pattern cannot possibly match, why wouldn't we report the error right then and there? The comment got reworded later but originally dates back to d25f03c (2019); perhaps @abgruszecki could explain his thinking on this...? Second, we're finding in debugging that So one possible fix plan is to address both of those: make Another possible fix plan would be to leave this stuff alone and catch it downstream in the "useless pattern checks" (redundancy checking) instead. (Though those checks are just warnings and we're supposed to be issuing a hard error here...) |
I tried searching around to see if this was a duplicate issue. I found a lot of issues around GADTs and pattern matching but didn't think the code in any of them were as simple as in this one. I hope this is not a duplicate.
Compiler version
3.0.0
Minimized code
Written with Scala 2 syntax for easy 🍎 to 🍏 comparison:
Result
The compilation succeeds in Scala 3.
Expectation
A compilation error similar to the one that I get if I try to compile the same code in Scala 2.13.6:
The text was updated successfully, but these errors were encountered: