-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Incorrect or missing exhaustivity warning when using type tests #9682
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
`Bind` has an extra type parameter `S` which does not exist in `Resource`, so when pattern matching on `Bind`, that type parameter is replaced by a skolem, we can get a reference to this skolem by using a pattern-bound type variable (here called `s`), this allows us to type the lambda parameter `r` correctly. Before this commit, `Any` was used instead of a type variable, this is unsound since `S` appears contravariantly in `fs` but didn't lead to any issue since it only appeared in the expression `fs(s)` (but if someone had accidentally written `fs(0)`, the compiler wouldn't have detected the error). This issue was identified by Dotty (though it somewhat confusingly reported that `Bind(_, _)` was missing from the match instead of reporting the use of an unchecked type test, I've minimized that and opened scala/scala3#9682), the remaining Dotty warnings are all unchecked type tests and they all seem like legitimate warnings to me. It's also worth noting that if we didn't have to cross-compile with Scala 2, we could just omit the type of the lambda parameter and Dotty would figure it out, so no explicit pattern-bound type variable would be needed at all :). I haven't tried it but this change should be backportable as-is to `series/2.x`.
`Bind` has an extra type parameter `S` which does not exist in `Resource`, so when pattern matching on `Bind`, that type parameter is replaced by a skolem (that is, a fresh abstract type whose bounds are those of `S` in `Bind`), we can get a reference to this skolem by using a pattern-bound type variable (here called `s`), this allows us to type the lambda parameter `r` correctly. Before this commit, `Any` was used instead of a type variable, this is unsound since `S` appears contravariantly in `fs` but didn't lead to any issue since it only appeared in the expression `fs(s)` (but if someone had accidentally written `fs(0)`, the compiler wouldn't have detected the error). This issue was identified by Dotty (though it somewhat confusingly reported that `Bind(_, _)` was missing from the match instead of reporting the use of an unchecked type test, I've minimized that and opened scala/scala3#9682), the remaining Dotty warnings are all unchecked type tests and they all seem like legitimate warnings to me. It's also worth noting that if we didn't have to cross-compile with Scala 2, we could just omit the type of the lambda parameter and Dotty would figure it out, so no explicit pattern-bound type variable would be needed at all :). I haven't tried it but this change should be backportable as-is to `series/2.x`.
`Bind` has an extra type parameter `S` which does not exist in `Resource`, so when pattern matching on `Bind`, that type parameter is replaced by a skolem (that is, a fresh abstract type whose bounds are those of `S` in `Bind`). This skolem doesn't have an accessible name, so to get a reference to it we need to use a pattern-bound type variable (here called `s`), this allows us to type the lambda parameter `r` correctly. Before this commit, `Any` was used instead of a type variable, this is unsound since `S` appears contravariantly in `fs` but didn't lead to any issue since it only appeared in the expression `fs(s)` (but if someone had accidentally written `fs(0)`, the compiler wouldn't have detected the error). This issue was identified by Dotty (though it somewhat confusingly reported that `Bind(_, _)` was missing from the match instead of reporting the use of an unchecked type test, I've minimized that and opened scala/scala3#9682), the remaining Dotty warnings are all unchecked type tests and they all seem like legitimate warnings to me. It's also worth noting that if we didn't have to cross-compile with Scala 2, we could just omit the type of the lambda parameter and Dotty would figure it out, so no explicit pattern-bound type variable would be needed at all :). I haven't tried it but this change should be backportable as-is to `series/2.x`.
There is at some point an intentional change to not reason in erasure semantics for exhaustivity check, and leave them to typetest check in later phases. One motivation is to better support GADT: sealed trait Expr[T]
case class IntExpr(x: Int) extends Expr[Int]
case class BooleanExpr(b: Boolean) extends Expr[Boolean]
def foo[T](x: Expr[T], y: Expr[T]) = (x, y) match {
case (IntExpr(_), IntExpr(_)) =>
case (BooleanExpr(_), BooleanExpr(_)) =>
} In the code above, if we reason in terms of type erasure, then the scrutinee has the type |
This comment has been minimized.
This comment has been minimized.
What about the other case, the one about the nested |
Good catch, I missed that part. I'll propose a fix for it. |
This produces no warning, but is not exhaustive:
This produces both an inexhaustivity and unchecked warnng, but it is exhaustive because of erasure:
(Adding a
case Bar(_) =>
should in fact produce an unreachability warning).The text was updated successfully, but these errors were encountered: