Skip to content
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

Track existentials in constrain_type_jkind #3686

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

goldfirere
Copy link
Collaborator

@goldfirere goldfirere commented Mar 12, 2025

The first commit shows the bad case, the second commit adds some helpful debugging support, and the third commit fixes the problem.

A few notes:

  • The extra line in for debugging must grossly be all on one line, because of the way the debug_printers.ml file is fed into the debugger via a very very dumb awk invocation. The alternative is to define this function in the compiler, but dependencies within the Btype module make this slightly annoying. Writing one very long line seemed the best option, unless you (for any value of "you") want to improve that awk invocation.
  • Interestingly, the fix required two mitigations: 1) track existentials in constrain_type_jkind (this is pretty straightforward, in the end), and 2) round up with-bounds in update_decl_jkind. Step 2 surprised me, but is clearly the right thing to do. Before this patch, we had type_jkinds in the wild with unbound variables in them. Horrors.
  • Sadly, the apply step in unbox_once copies the unboxed type's field, which means that the variable changes identity. I worked around this by including the existentials within the same copy scope, but this makes me very sad. Either the copy mechanism should be taught not to copy existentials at generic-level (which seems hard and probably wrong), or maybe some cleverer interaction with the copy_scope could simplify this. Staring at this a bit showed no obvious way to get what I want, but I'm still a little mystefied by e.g. Tsubst. I'm confident that what I did is correct, but not confident that it's as good as it could be (from both a coding clarity and performance standpoint). Very happy for pointers here, probably from @lpw25 or @stedolan.

Review: @ccasin

@goldfirere goldfirere force-pushed the rae/accept-shared-modality branch from 9cad1f3 to 0ccba98 Compare March 12, 2025 21:21
Base automatically changed from rae/accept-shared-modality to main March 12, 2025 21:45
@goldfirere goldfirere force-pushed the rae/existentials-in-constrain branch from 7c3bfe6 to d463992 Compare March 12, 2025 22:45
@lpw25
Copy link
Collaborator

lpw25 commented Mar 13, 2025

Step 2 surprised me, but is clearly the right thing to do. Before this patch, we had type_jkinds in the wild with unbound variables in them.

In the long run, I think it would be better if we could inject kinds back into the space of types used for with-kinds. That would give more precise with-kinds here. Alternatively, with-kinds could bind type variables, but that seems worse to me.

Sadly, the apply step in unbox_once copies the unboxed type's field, which means that the variable changes identity. I worked around this by including the existentials within the same copy scope, but this makes me very sad.

I think that probably the right solution here is to leave apply as it is and use:

let apply ty2 existentials =
   apply env (decl.type_params @ existentials) ty2 (args @ existentials)
in

in unbox_once. Treating ty as a type expression with both decl.type_params and existentials as parameters, which it essentially is, and then filling in the existentials parameters with themselves.

@goldfirere
Copy link
Collaborator Author

I think that probably the right solution here is to leave apply as it is and use:

Yes that seems simpler. Thanks for taking a look. I will try.

@goldfirere
Copy link
Collaborator Author

I just pushed a new implementation of how we track bound variables. The old one did a lot of building of sets, etc., which were almost never consulted. I also considered just tracking a list of type_expr (and then converting to a set in constrain_type_jkind), but concatenating lists is painful. So I thought I'd just encode things pretty directly: we care sometimes about emptiness (which is cheap anyway), and rarely care about membership.

I have not done perf testing here, but this just has to be better than what I wrote before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants