-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Match types' type binds are unsound #6570
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
We've just considered fixing this problem by checking that the scrutinee does not contain abstract types at the "toplevel" (as leaves of union of intersections). This would fix the following example: type M[t] = t match {
case Cov[t] => N[t]
}
[T <: Cov[Int]] => M[T] However, it does nothing for the following one: type M[t] = (Int, t) match {
case (Int, Cov[t]) => N[t]
}
[T <: Cov[Int]] => M[T] The problem seems to lie with being able to "destructure" an abstract type, i.e. bind type variables to its subcomponents. This is reinforced by the observation that, as far as I can tell, it's perfectly sound to bind a type variable directly to an abstract type: type F[t] = t match { case List[u] => u }
def foo[U, T <: List[U](...): F[T] // no unsoundness possible here |
Fix #6570: Don't reduce match types with empty scrutinies
It is possible to exploit the way match types bind type variable to make match types "forget" they are dealing with an abstract type. I have multiple examples, but possibly the one easiest to understand is:
Essentially, what seems to happen is that when reducing
M
, we pick theCov[t]
case, bindt
to a non-abstract type and happily proceed with the reduction. It's illustrating to consider thatfoo
would not compile if we definedM
like:The other "exploits"
are here
/cc @OlivierBlanvillain
The text was updated successfully, but these errors were encountered: