You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.
A match type is apparently not a subtype of the union of it branches. So this for instance does not work:
defflip: (x: 0|1) => x.typematch { case0=>1case1=>0 } =???valn:0|1=if???then0else1
flip(n) // works
flip(flip(n)) // does not work: we don't have flip(n).type <: 0 | 1valm: n.typematch { case0=>1case1=>0 } = flip(n)
flip(m) // does not work
I think it ought to work, because whatever a match type reduces to, it is always one of its right-hand-sides, given some values for the types extracted from the pattern.
Conceptually, the match type would be a subtype of the union of the match right-hand sides with the extracted type variables converted to wildcards (or otherwise avoided); for example we should treat X match { case List[t] => (t, t) } as a subtype of (_, _).
The algorithm could be the following: when solving a subtyping constraint with a match type on the left, try each right-hand side of the match type separately, making the pattern-extracted type variables rigid skolem variables (it looks like this can be done with the typer.ProtoTypes.constrained(_: TypeLambda) method).
I have tried adapting recur in TypeComparer to try the alternatives of a match type:
But this has problems with recursive match types: indeed, for these we will get into infinite deep subtyping recursions!
I did not find a way to detect if a match type is recursive. However, it should be possible to use the following approximation: if the match type has an explicit bound, assume it may be recursive; otherwise, use the algorithm above. This is sound because a recursive match type without a bound will give a cycle error anyways.
There is currently no way to test if a bound was provided explicitly (currently Any is picked during type assignment if no bound was given), but it could probably be done.
An alternative would be to pick the type union as the bound itself when no bound is given.
What do you think?
The text was updated successfully, but these errors were encountered:
This should be re-opened a a feature request. I believe it would be not at all easy to implement since it can cause new cycles. What is the upper bound of a recursive match type?
@odersky my understanding was that a recursive match type requires an explicit user-provided upper bound, otherwise it raises a cyclic error. At least this is the behavior that I have observed.
So unless I am mistaken on that point, I do not see how this can create more cycles.
A match type is apparently not a subtype of the union of it branches. So this for instance does not work:
I would have expected it to work.
This was originally reported here: scala/scala3#7835 (comment).
I think it ought to work, because whatever a match type reduces to, it is always one of its right-hand-sides, given some values for the types extracted from the pattern.
Conceptually, the match type would be a subtype of the union of the match right-hand sides with the extracted type variables converted to wildcards (or otherwise avoided); for example we should treat
X match { case List[t] => (t, t) }
as a subtype of(_, _)
.The algorithm could be the following: when solving a subtyping constraint with a match type on the left, try each right-hand side of the match type separately, making the pattern-extracted type variables rigid skolem variables (it looks like this can be done with the
typer.ProtoTypes.constrained(_: TypeLambda)
method).I have tried adapting
recur
inTypeComparer
to try thealternatives
of a match type:But this has problems with recursive match types: indeed, for these we will get into infinite deep subtyping recursions!
I did not find a way to detect if a match type is recursive. However, it should be possible to use the following approximation: if the match type has an explicit bound, assume it may be recursive; otherwise, use the algorithm above. This is sound because a recursive match type without a bound will give a cycle error anyways.
There is currently no way to test if a bound was provided explicitly (currently
Any
is picked during type assignment if no bound was given), but it could probably be done.An alternative would be to pick the type union as the bound itself when no bound is given.
What do you think?
The text was updated successfully, but these errors were encountered: