-
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
Match type reduction of nested type constructors does not propagate contravariance #17121
Comments
I believe the problem and the fix will be either in matchtype reduction or iun GADT constraint solving. |
This isn't supposed to work, right? class C[-T]
type F[X] = X match
case C[C[t]] => t
def x: F[C[Any]] = ??? But it works and we have ==> normalize F[C[Any]]?
==> reduce match type C[Any] match {
case C[C[t]] => t
} 1269408193?
<== reduce match type C[Any] match {
case C[C[t]] => t
} 1269408193 = Nothing
<== normalize F[C[Any]] = Nothing |
Well |
Well, then it is not a bug. It's supposed to widen the type resulting from matching, not the original one. So in REPL cases, it widens the match, not the whole type. In the case of class C[-T]
type F[X] = X match
case C[C[C[C[t]]]] => t // 4 C
def x: F[C[C[C[Any]]]] = ??? // 3 C You get If we change this to fit the original example pattern, then in type F[X] = X match
case List[t] => t
def x: F[List[Nothing]] = ??? we would get |
What is your definition of "the type resulting from matching"? The only reasonable interpretation I can come up with is the right-hand-side of the |
For class C[-T]
type F[X] = X match
case C[C[t]] => t
def x: F[C[C[_]]] = ??? It widens In case of class C[-T]
type F[X] = X match
case C[C[t]] => t
def x: F[C[Any]] = ??? It widens For |
You haven't answered my question:
You give me two examples, both for the same match type with the pattern |
I thought illustrating with examples was better, I am very sorry. The type resulting from matching is the type we get after we unify scrutinee with the pattern. This type for I don't understand the inconsistency with covariance, it seems to work correctly -- if you want to have a widening of (Also, it's very useful to think of |
Although it's pretty counterintuitive, I agree! But trying to change this is a recipe for disaster. The problem is -- what do you widen even? If we widen the pattern we may run into the problem I have described above. And you can't really unify them so that you have the desired behavior. |
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Closes scala#17121. Closes scala#17944. Closes scala#18488.
Compiler version
3.3.0-RC2
Minimized code
As a REPL session:
Output
In every case,
t
is instantiated toAny
when the innermost type constructor is covariant, and toNothing
when the innermost type constructor is contravariant. The instantiation completely disregards any contravariant type constructor on the "path" from the top scrutinee down to the type parameter.Expectation
The spec says:
I expect "that appear contravariantly" to actually take the whole path into account. So I expected the results shown in comments in the above REPL session.
Perhaps nesting type constructors in contravariant position of type match patterns should not even be allowed in the first place? It's very unclear to me how to specify that. Indeed, it means that we need to reverse the whole type match logic when we get in those situations. Normally, we unify a scrutinee
S
with a patternP
in a way that makesS <: P
. It is quite clear what that means even whenP
is an applied typePc[...Pi]
, because we can take thebaseType(S, Pc)
and extract the arguments from that. But now we should unify in a way that makesPc[...Pi] <: S
. What does that mean in general (without resorting to type inference and constraints, which do not exist after typer anymore)?The text was updated successfully, but these errors were encountered: