-
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
Canonicalize capture variable subtype comparisons #22289
Conversation
Fixes scala#22103 Subtype problems where at least one side is a type variable representing a capture variable are canonicalized to capturing type comparisons on the special `CapSet` for the universe capture sets. For example, `C <: CapSet^{C^}` becomes `CapSet^{C^} <: CapSet^{C^}`, and `A <: B` becomes `CapSet^{A^} <: CapSet^{B^}` if both `A` and `B` are capture variables.
val c3: C = d_e_f1 // error | ||
val c4: C = f1 // error | ||
val e4: E = f1 // error | ||
val e5: E = d1 // error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should fail but currently doesn't. We now canonicalize the subtype test D <: E
(fails) to CapSet^{D^} <: CapSet^{E^}
(succeeds). It appears the subcapturing implementation does not handle this correctly.
Can you push this to dotty-staging? Then we can collaborate to maybe fix the problem with the failing test. |
I think the problem of the failing test is with And if we handle this correctly, it should also be possible to write things like def f[C^, D^, E <: C | D](...) = ... which means that or: def f[C^, D^, E <: C & D](...) = ... which means that |
@Linyxus exactly! That will be the next step. |
The continuation: #22299 |
Fixes #22103 Subtype problems where at least one side is a type variable representing a capture variable are canonicalized to capturing type comparisons on the special `CapSet` for the universe capture sets. For example, `C <: CapSet^{C^}` becomes `CapSet^{C^} <: CapSet^{C^}`, and `A <: B` becomes `CapSet^{A^} <: CapSet^{B^}` if both `A` and `B` are capture variables. Supersedes #22183 and #22289. This solution is overall cleaner and does not require adding a new bit to the TypeComparer's ApproxState. TODOs/Issues/Questions: - [x] Fix extension method in test [cc-poly-varargs.scala](https://github.com/dotty-staging/dotty/blob/capture-subtyping-canon/tests/pos-custom-args/captures/cc-poly-varargs.scala). Currently causes an infinite regress. - [x] Fix the aftermath * tests/neg-custom-args/captures/lazylists-exceptions.scala * tests/neg-custom-args/captures/exceptions.scala * tests/neg-custom-args/captures/real-try.scala * tests/run-custom-args/captures/colltest5 - [x] Some negative cases in test [capture-vars-subtyping.scala](https://github.com/dotty-staging/dotty/blob/capture-subtyping-canon/tests/neg-custom-args/captures/capture-vars-subtyping.scala) pass: `D <: E` fails, but its canonicalized form `CapSet^{D^} <: CapSet^{E^}` now succeeds. Potential problem in the subcapturing implementation. - [x] ~Extend to intersection/unions `def f[C^, D^, E <: C | D, F <: C & D](...) = ...` etc.~ Lacking good uses cases, not planned right now. - [X] ~If we have `C^` declared in the current context, should there be a difference between `C` vs. `C^` for subsequent mentions? We currently do, but seems a bit too subtle for users.~ Will be addressed by a new scheme for declaring capture variables using context bounds.
Fixes #22103
Subtype problems where at least one side is a type variable representing a capture variable are canonicalized to capturing type comparisons on the special
CapSet
for the universe of capture sets. For example,C <: CapSet^{C^}
becomesCapSet^{C^} <: CapSet^{C^}
, andA <: B
becomesCapSet^{A^} <: CapSet^{B^}
if bothA
andB
are capture variables.Supersedes #22183. This solution is overall cleaner and does not require adding a new bit to the TypeComparer's ApproxState.