new solver: make all goal evaluation able to be automatically rerun #108896
Merged
bors merged 9 commits intorust-lang:masterfrom Mar 21, 2023
Merged
new solver: make all goal evaluation able to be automatically rerun #108896bors merged 9 commits intorust-lang:masterfrom
bors merged 9 commits intorust-lang:masterfrom
Conversation
Collaborator
|
Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor |
c2ccd21 to
c95a1a6
Compare
Collaborator
|
☔ The latest upstream changes (presumably #109019) made this pull request unmergeable. Please resolve the merge conflicts. |
d0c88bd to
00e91d4
Compare
This comment has been minimized.
This comment has been minimized.
1aa44d6 to
ed63201
Compare
lcnr
reviewed
Mar 17, 2023
Contributor
lcnr
left a comment
There was a problem hiding this comment.
happy with this code, some final (hopefully) nits and ideas
e6f21f6 to
ce14a1e
Compare
lcnr
reviewed
Mar 17, 2023
480ddf0 to
9df35a5
Compare
Contributor
|
@bors r+ rollup |
Collaborator
Dylan-DPC
added a commit
to Dylan-DPC/rust
that referenced
this pull request
Mar 21, 2023
…lcnr new solver: make all goal evaluation able to be automatically rerun It is generally wrong to call `evaluate_goal` multiple times or `evaluate_goal` and `evaluate_all` for the same `QueryResult` without correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion in `evaluate_goal` firing because rerunning the goal will lead to a more accurate `QueryResult`. Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the `EvalCtxt` and then run all the added goals in a loop so that `evaluate_goal`/`evaluate_all` is not necessary to call manually. There are a few complications for making everything work "right": 1. the `normalizes-to` hack that replaces the rhs with an unconstrained infer var requires special casing in the new `try_evaluate_added_goals` function similar to how `evaluate_goal`'s assertion special cases that hack. 2. `assemble_candidates_after_normalizing_self_ty`'s normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurate `QueryResult` when rerunning the projection/trait goal which can effect the `QueryResult` of the projection/trait goal. This is implemented via `EvalCtxt::probe`'s closure's `EvalCtxt` inheriting the added goals of the `EvalCtxt` that `probe` is called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals. I made `make_canonical_response` evaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to call `response_no_constraints` (which from the name is obviously weird). The visibility of `evaluate_goal` means that it can be called from various `compute_x_goal` or candidate assembly functions, this is generally wrong and we should never call `evaluate_goal` manually, instead we should be calling `add_goal`/`add_goals`. This is solved by moving `evaluate_goal` `evaluate_canonical_goal` and `compute_goal` into `eval_ctxt`'s module and making them private so they cannot be called from elsewhere, forcing people to call `add_goal/s` and `evaluate_added_goals_and_make_canonical_resposne`/`try_evaluate_added_goals` --- Other changes: - removed the `&& false` that was introduced to the assertion in `evaluate_goal` in rust-lang#108839 - remove a `!self.did_overflow()` requirement in `search_graph.is_empty()` which causes goals that overflow to ICE - made `EvalCtxt::eq` take `&mut self` and add all the nested goals via `add_goals` instead of returning them as 99% of call sites just immediately called `EvalCtxt::add_goals` manually. r? `@lcnr`
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this pull request
Mar 21, 2023
…lcnr new solver: make all goal evaluation able to be automatically rerun It is generally wrong to call `evaluate_goal` multiple times or `evaluate_goal` and `evaluate_all` for the same `QueryResult` without correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion in `evaluate_goal` firing because rerunning the goal will lead to a more accurate `QueryResult`. Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the `EvalCtxt` and then run all the added goals in a loop so that `evaluate_goal`/`evaluate_all` is not necessary to call manually. There are a few complications for making everything work "right": 1. the `normalizes-to` hack that replaces the rhs with an unconstrained infer var requires special casing in the new `try_evaluate_added_goals` function similar to how `evaluate_goal`'s assertion special cases that hack. 2. `assemble_candidates_after_normalizing_self_ty`'s normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurate `QueryResult` when rerunning the projection/trait goal which can effect the `QueryResult` of the projection/trait goal. This is implemented via `EvalCtxt::probe`'s closure's `EvalCtxt` inheriting the added goals of the `EvalCtxt` that `probe` is called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals. I made `make_canonical_response` evaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to call `response_no_constraints` (which from the name is obviously weird). The visibility of `evaluate_goal` means that it can be called from various `compute_x_goal` or candidate assembly functions, this is generally wrong and we should never call `evaluate_goal` manually, instead we should be calling `add_goal`/`add_goals`. This is solved by moving `evaluate_goal` `evaluate_canonical_goal` and `compute_goal` into `eval_ctxt`'s module and making them private so they cannot be called from elsewhere, forcing people to call `add_goal/s` and `evaluate_added_goals_and_make_canonical_resposne`/`try_evaluate_added_goals` --- Other changes: - removed the `&& false` that was introduced to the assertion in `evaluate_goal` in rust-lang#108839 - remove a `!self.did_overflow()` requirement in `search_graph.is_empty()` which causes goals that overflow to ICE - made `EvalCtxt::eq` take `&mut self` and add all the nested goals via `add_goals` instead of returning them as 99% of call sites just immediately called `EvalCtxt::add_goals` manually. r? ``@lcnr``
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this pull request
Mar 21, 2023
…lcnr new solver: make all goal evaluation able to be automatically rerun It is generally wrong to call `evaluate_goal` multiple times or `evaluate_goal` and `evaluate_all` for the same `QueryResult` without correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion in `evaluate_goal` firing because rerunning the goal will lead to a more accurate `QueryResult`. Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the `EvalCtxt` and then run all the added goals in a loop so that `evaluate_goal`/`evaluate_all` is not necessary to call manually. There are a few complications for making everything work "right": 1. the `normalizes-to` hack that replaces the rhs with an unconstrained infer var requires special casing in the new `try_evaluate_added_goals` function similar to how `evaluate_goal`'s assertion special cases that hack. 2. `assemble_candidates_after_normalizing_self_ty`'s normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurate `QueryResult` when rerunning the projection/trait goal which can effect the `QueryResult` of the projection/trait goal. This is implemented via `EvalCtxt::probe`'s closure's `EvalCtxt` inheriting the added goals of the `EvalCtxt` that `probe` is called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals. I made `make_canonical_response` evaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to call `response_no_constraints` (which from the name is obviously weird). The visibility of `evaluate_goal` means that it can be called from various `compute_x_goal` or candidate assembly functions, this is generally wrong and we should never call `evaluate_goal` manually, instead we should be calling `add_goal`/`add_goals`. This is solved by moving `evaluate_goal` `evaluate_canonical_goal` and `compute_goal` into `eval_ctxt`'s module and making them private so they cannot be called from elsewhere, forcing people to call `add_goal/s` and `evaluate_added_goals_and_make_canonical_resposne`/`try_evaluate_added_goals` --- Other changes: - removed the `&& false` that was introduced to the assertion in `evaluate_goal` in rust-lang#108839 - remove a `!self.did_overflow()` requirement in `search_graph.is_empty()` which causes goals that overflow to ICE - made `EvalCtxt::eq` take `&mut self` and add all the nested goals via `add_goals` instead of returning them as 99% of call sites just immediately called `EvalCtxt::add_goals` manually. r? ```@lcnr```
Noratrieb
added a commit
to Noratrieb/rust
that referenced
this pull request
Mar 21, 2023
…lcnr new solver: make all goal evaluation able to be automatically rerun It is generally wrong to call `evaluate_goal` multiple times or `evaluate_goal` and `evaluate_all` for the same `QueryResult` without correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion in `evaluate_goal` firing because rerunning the goal will lead to a more accurate `QueryResult`. Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the `EvalCtxt` and then run all the added goals in a loop so that `evaluate_goal`/`evaluate_all` is not necessary to call manually. There are a few complications for making everything work "right": 1. the `normalizes-to` hack that replaces the rhs with an unconstrained infer var requires special casing in the new `try_evaluate_added_goals` function similar to how `evaluate_goal`'s assertion special cases that hack. 2. `assemble_candidates_after_normalizing_self_ty`'s normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurate `QueryResult` when rerunning the projection/trait goal which can effect the `QueryResult` of the projection/trait goal. This is implemented via `EvalCtxt::probe`'s closure's `EvalCtxt` inheriting the added goals of the `EvalCtxt` that `probe` is called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals. I made `make_canonical_response` evaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to call `response_no_constraints` (which from the name is obviously weird). The visibility of `evaluate_goal` means that it can be called from various `compute_x_goal` or candidate assembly functions, this is generally wrong and we should never call `evaluate_goal` manually, instead we should be calling `add_goal`/`add_goals`. This is solved by moving `evaluate_goal` `evaluate_canonical_goal` and `compute_goal` into `eval_ctxt`'s module and making them private so they cannot be called from elsewhere, forcing people to call `add_goal/s` and `evaluate_added_goals_and_make_canonical_resposne`/`try_evaluate_added_goals` --- Other changes: - removed the `&& false` that was introduced to the assertion in `evaluate_goal` in rust-lang#108839 - remove a `!self.did_overflow()` requirement in `search_graph.is_empty()` which causes goals that overflow to ICE - made `EvalCtxt::eq` take `&mut self` and add all the nested goals via `add_goals` instead of returning them as 99% of call sites just immediately called `EvalCtxt::add_goals` manually. r? ````@lcnr````
bors
added a commit
to rust-lang-ci/rust
that referenced
this pull request
Mar 21, 2023
Rollup of 10 pull requests Successful merges: - rust-lang#106434 (Document `Iterator::sum/product` for Option/Result) - rust-lang#108326 (Implement read_buf for a few more types) - rust-lang#108842 (Enforce non-lifetime-binders in supertrait preds are not object safe) - rust-lang#108896 (new solver: make all goal evaluation able to be automatically rerun ) - rust-lang#109124 (Add `dist.compression-profile` option to control compression speed) - rust-lang#109240 (Walk un-shifted nested `impl Trait` in trait when setting up default trait method assumptions) - rust-lang#109385 (fix typo) - rust-lang#109386 (add myself to mailmap) - rust-lang#109390 (Custom MIR: Support aggregate expressions) - rust-lang#109408 (not *all* retags might be explicit in Runtime MIR) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
It is generally wrong to call
evaluate_goalmultiple times orevaluate_goalandevaluate_allfor the sameQueryResultwithout correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion inevaluate_goalfiring because rerunning the goal will lead to a more accurateQueryResult.Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the
EvalCtxtand then run all the added goals in a loop so thatevaluate_goal/evaluate_allis not necessary to call manually.There are a few complications for making everything work "right":
the
normalizes-tohack that replaces the rhs with an unconstrained infer var requires special casing in the newtry_evaluate_added_goalsfunction similar to howevaluate_goal's assertion special cases that hack.assemble_candidates_after_normalizing_self_ty's normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurateQueryResultwhen rerunning the projection/trait goal which can effect theQueryResultof the projection/trait goal.This is implemented via
EvalCtxt::probe's closure'sEvalCtxtinheriting the added goals of theEvalCtxtthatprobeis called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals.I made
make_canonical_responseevaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to callresponse_no_constraints(which from the name is obviously weird).The visibility of
evaluate_goalmeans that it can be called from variouscompute_x_goalor candidate assembly functions, this is generally wrong and we should never callevaluate_goalmanually, instead we should be callingadd_goal/add_goals. This is solved by movingevaluate_goalevaluate_canonical_goalandcompute_goalintoeval_ctxt's module and making them private so they cannot be called from elsewhere, forcing people to calladd_goal/sandevaluate_added_goals_and_make_canonical_resposne/try_evaluate_added_goalsOther changes:
&& falsethat was introduced to the assertion inevaluate_goalin Canonicalize root var when making response from new solver #108839!self.did_overflow()requirement insearch_graph.is_empty()which causes goals that overflow to ICEEvalCtxt::eqtake&mut selfand add all the nested goals viaadd_goalsinstead of returning them as 99% of call sites just immediately calledEvalCtxt::add_goalsmanually.r? @lcnr