-
Notifications
You must be signed in to change notification settings - Fork 21
use of custom unapply breaks exhaustivity checking #10660
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
Comments
Well of course it breaks exhaustivity checking, because the match might indeed not be exhaustive, if you replace the body of your |
Then it is broken in two ways. The one I care about is that it no longer warns that Just is not covered. |
Replace the body of your |
But that is then broken. The custom extractor is against Maybe, so perhaps there is no way to fix this. |
You know that. The compiler has no idea. |
yes, but that's just further evidence that the compiler should be more cautious, not less. It's almost like the exhaustiveness checker is assuming that Boolean unapply is returning true. |
So you would like a warning every time the compiler cannot prove exhaustiveness (as opposed to when it can prove non-exhaustiveness)? |
That would be pretty good, yes! Effectively forcing pattern matches only for destructuring. I'm aware the motivating example is therefore excluded. |
I'd love to have an annotation that fails compilation on non-exhaustive matches (somewhat like |
I did the same search when I wanted to close this as a dupe, and realised this is the closest we have. But my ticket search foo is pretty bad. |
I added a custom unapply to the scalaz IList, looking like this object :: {
def unapply[A](xs: ICons[A]): Option[(A, IList[A])] = xs match {
case ICons(head, tail) => Some(head -> tail)
}
} even though the input type is
in addition, the definition of an def unapplySeq[A](ilist: IList[A]): Option[Seq[A]] = Some(ilist.toList) It is debatable what should and shouldn't disable the matcher. But I feel it shouldn't happen silently (there is a scalafix request for this). |
In addition to this, it would be very nice if the exhaustive checker could special-case extractors that return Conceptually, the def unapply[A](xs: ICons[A]): Some[(A, IList[A])] = xs match {
case ICons(head, tail) => Some(head -> tail)
} It compiles, but neither Dotty nor Scalac leverage the additional knowledge. This would address @sjrd's remark that the compiler currently has no clue whether an extractor is fallible or not, although that is arguably an important semantic distinction. Would also probably help with scala/scala3#2575. Perhaps that should be a separate ticket. |
They both do in some situations, for example in: sealed trait Base
case class One() extends Base
object Foo {
def unapply(x: Base): Option[Int] =
Some(0)
}
object Test {
def test(x: Base) =
x match {
case Foo(a) => a
}
} You get a "match may not be exhaustive" warning for Dotty, if |
@smarter you're right, they seem to do the right thing for |
@LPTK Feel free to open issues for any problem you encounter, it helps! |
I find this issue interesting and felt it was worth mentioning that (as best I can tell) custom
|
@jcracknell maybe we should open another issue for that. It does seem a little surprising, and I think emitting a warning for this would be a good idea. |
In 2.12.4 the following code (correctly) warns on compile due to exhaustivity checking
but the following, with an alternative encoding of
Empty
(#10659) compiles without warningGuessing, it looks like the presence of the "custom"
unapply
causes the more aggressive checkers not to trigger. Perhaps the presence of the custom unapply should only disable the aggressive checking around theEmpty
, not around the entire ADTMaybe
.// @xuwei-k
The text was updated successfully, but these errors were encountered: