-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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.