-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
-Z trait-solver=next
: Deduplicate region constraints in query responses
#111172
Conversation
r? @b-naber (rustbot has picked a reviewer for you, use r? to override) |
|
Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor Some changes occurred in src/tools/cargo cc @ehuss |
Aaaah my bad, it appears I screwed something up and staged some temp file changes to src/tools/cargo - if the rust bot pinged you about that, you can safely disregard this PR - I'll fix it once I figure out how to. Edit: It appears that the current standings are git: 1, me: 0. I've tried doing |
This comment has been minimized.
This comment has been minimized.
also r? @lcnr |
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.
haven't looked at the algorithm yet, but some initial thoughts about to slightly simplify this impl.
you commited changes to cargo in 4bc7dd1b8275b129c89657852c446abe2338f471, see https://rustc-dev-guide.rust-lang.org/git.html#i-changed-a-submodule-by-accident for elp on how to solve this.
Is your algorithm something which can be viewed as:
- map rust constraints to a graph
- solve a known problem on graphs (or multiple problems in sequence)
- map the result back to rust constraints
iiuc DedupSolver::dedup
calls a bunch of subroutines and at least some of them may be equivalent to something on ordinary graphs. If so, it would be good to 1. use or mention the terminology used for graphs. generally, DedupSolver::dedup
seems like the core of your approach, so this might be a good place to explain what's going on there. Right now the meaning of "category" and "rule" isn't immediately clear to me.
compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical/dedup_solver/solver.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical/dedup_solver/mod.rs
Outdated
Show resolved
Hide resolved
Yeah, the deduplication is essentially just one big graph algorithm :) The constraints are vertices, and if two constraints can potentially be merged, they have an edge between them, and the variable mapping that would merge them is the edge label. I suppose a "category" can best be described as an isolated clique in the graph, i.e. a clique that has no edges joining it to any other clique. "Rule" is just my internal representation of a rust constraint, I just used it during development cuz "rule" is shorter, but I'll go ahead and replace it with constraint now I'd like to make a few minor changes to the dedup solver, so right now I didn't add any additional comments documenting that (so it probably can't be reviewed yet) - once I settle those, I'll put additional comments and explanations for review. |
@ndrewxie please use a rebase instead of a merge if you want to update your branch -- we have no "no merge commit" policy in the repo |
Alright, gocha. Do you have any pointers for how I can undo my mistake? (sorry, I'm not too good with git...) |
I think you can just do |
Alright, I undid my erroneous merge. When I try doing git pull --rebase I'm getting a lot of merge conflicts, however. What's the best way to deal with this? Also sorry I haven't had too much time to work on this recently, been wrapping up another PR and have a bunch of mandatory testing. In a couple more days, I should have more time to clean up my implementation and document it a bit more for review. Also just one question regarding lcnr's comment about deduplicating in |
the information about universes is also available before we have the canonical response, because how could we otherwise create the response? 😁 you can look at how canonicalization gets the universe for existential variables, iirc we use |
Haha I guess you're right, thanks for the help! I guess the new motto going forward is, "if you can't find something, just ctrl + f under InfCtxt" 😄 EDIT: Just now I realized that my whole constraint_walker stuff could be done with a TypeFolder, which would be far cleaner and be less error-prone. I'm currently re-writing that component. |
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.
the way you currently lower region constraints to a set of variables feels wrong to me 🤔 didn't yet go over the extern solver in detail, but if you have &'var (): 'static
and &'static (): 'var
they should result in the same input for the solver afaict.
This is currently somewhat difficult for me to review and understand as there are a few things which feel a bit weird '^^ would you be up to take some time to chat about this in sync? either via text on zulip or via zoom?
Something else which would be really valuable would be some example lowerings from rust syntax to the solver constraints. You already did some manual lowering for the tests and having some small examples of "input X lowers to these constraints" would be very helpful.
compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical/dedup_solver/constraint_walker.rs
Outdated
Show resolved
Hide resolved
Just to confirm, this is because if var outlives static, then var must be static, so therefore static outlives var too, right? I guess this makes sense, but how could we apply it to more complicated types like
Sure! Zulip would be more convenient for me, but both work. Github tells me you're in Germany, so on weekends any time after 15:00 CEST (9:00 AM EDT for me) should be fine. On weekdays, I'm basically limited to after 4:00 PM EDT, so after 22:00 CEST should work. But yeah the solver in its present state isn't very clear - I'll rework it a bit today and add the comments you asked for. The solver is certainly related to graph theory, but my understanding of that is admittedly limited, and I can't really find a neat way to map the majority of it onto pre-existing graph theory problems... |
woops, I meant that we should not consider them to be equal but iirc your solver currently generates the same constraints for them. What are the generated constraints for |
Well, yes and no - the solver does extract the same variables for both (if we say These cliques get refined later in the solving process, but when we first scan the constraints and extract variables, we create "rough" cliques by the following procedure:
In the case you provided, two cliques would be made:
My apologies if this was poorly explained in the comments (or is poorly explained now 😅). I'll put in better documentation for this part later today. |
☔ The latest upstream changes (presumably #111473) made this pull request unmergeable. Please resolve the merge conflicts. |
…/tools/cargo (hopefully)
…canonicalization, reworked constraint_walker to use TypeFolder/TypeFoldable
…wer constraints over older
…wer constraints over older (2)
Hi @lcnr, just letting you know that this PR has been updated. I think it's ready for review whenever you have a chance. Thanks! 🙂 |
closing this for now as I hope the pattern fixed here does not occur in actual code so it adds complexity to the solver. I am still thankful to @ndrewxie for working on this and chatting about it on zulip, as this provided me with a far better understanding of what's going on here and also uncovered a bigger issue of our overflow handling. |
An attempt at fixing #109764 .
This is a MVP version, so I'm opening a PR primarily so others can review and critique it (is this correct protocol? or should a work-in-progress like this be handled differently?). I'm sure there's many points where my implementation is incorrect, but right now it does compile all the snippets provided in the issue (which I put into 1 test file called dedup-vars), and doesn't break any other code (at least, nothing that's detected by any tests :P)
Right now, I'm deduplicating the output of canonicalizing the Response - is this correct?
The idea is as follows:
.outlives
and.member_constraints
) matter? Right now, I'm not making any effort to preserve this order, but if it's needed I suppose I could do so, it'll just be less cleanAlso just a quick question, what exactly is opaque_types? I couldn't find much documentation about it, and reading the code didn't give any significant clues... Should this deduplication handle that in some way?