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

Allow to feed a value in another query's cache and remove WithOptConstParam #96840

Merged
merged 10 commits into from
Apr 21, 2023

Conversation

cjgillot
Copy link
Contributor

@cjgillot cjgillot commented May 8, 2022

I used it to remove WithOptConstParam queries, as an example.

The idea is that a query (here typeck(function)) can write into another query's cache (here type_of(anon const)). The dependency node for type_of would depend on all the current dependencies of typeck.

There is still an issue with cycles: if type_of(anon const) is accessed before typeck(function), we will still have the usual cycle. The way around this issue is to ensure that typeck(function) is called before accessing type_of(anon const).

When replayed, we may the following cases:

  • typeck is green, in that case type_of is green too, and all is right;
  • type_of is green, typeck may still be marked as red (it depends on strictly more things than type_of) -> we verify that the saved value and the re-computed value of type_of have the same hash;
  • type_of is red, then typeck is red -> it's the caller responsibility to ensure typeck is recomputed before type_of.

As anon consts have their own DefPathData, it's not possible to have the def-id of the anon-const point to something outside the original function, but the general case may have to be resolved before using this device more broadly.

There is an open question about loading from the on-disk cache. If typeck is loaded from the on-disk cache, the side-effect does not happen. The regular type_of implementation can go and fetch the correct value from the decoded typeck results, and the dep-graph will check that the hashes match, but I'm not sure we want to rely on this behaviour.

I specifically allowed to feed the value to type_of from inside a call to type_of. In that case, the dep-graph will check that the fingerprints of both values match.

This implementation is still very sensitive to cycles, and requires that we call typeck(function) before typeck(anon const). The reason is that typeck(anon const) calls type_of(anon const), which calls typeck(function), which feeds type_of(anon const), and needs to build the MIR so needs typeck(anon const). The latter call would not cycle, since type_of(anon const) has been set, but I'd rather not remove the cycle check.

@rustbot rustbot added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. labels May 8, 2022
@rust-log-analyzer

This comment has been minimized.

impl<$tcx> TyCtxtFeed<$tcx> {
$($(#[$attr])*
#[inline(always)]
pub fn $name<V>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to only allow this for queries which explicitly opt-in? And then maybe not allow setting any provider for such queries. I think that makes the information flow a lot clearer.

@cjgillot cjgillot changed the title WIP: Allow to feed a value in another's cache WIP: Allow to feed a value in another query's cache May 8, 2022
@bors
Copy link
Contributor

bors commented May 9, 2022

☔ The latest upstream changes (presumably #96473) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 9, 2022
@cjgillot cjgillot closed this Jul 30, 2022
@cjgillot cjgillot reopened this Sep 4, 2022
@rustbot rustbot added the A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) label Sep 4, 2022
@rustbot
Copy link
Collaborator

rustbot commented Sep 4, 2022

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

Some changes occurred in const_evaluatable.rs

cc @lcnr

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Copy link
Contributor Author

@cjgillot cjgillot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks rustbot. So much for the discretion of a WIP PR 😄

compiler/rustc_query_system/src/dep_graph/graph.rs Outdated Show resolved Hide resolved
@cjgillot cjgillot changed the title WIP: Allow to feed a value in another query's cache Allow to feed a value in another query's cache Sep 4, 2022
@cjgillot
Copy link
Contributor Author

cjgillot commented Sep 4, 2022

r? compiler

@bors
Copy link
Contributor

bors commented Sep 5, 2022

☔ The latest upstream changes (presumably #100759) made this pull request unmergeable. Please resolve the merge conflicts.

@lcnr
Copy link
Contributor

lcnr commented Sep 5, 2022

looked through this PR and I am really happy about not seeing WithOptConstParam anymore ✨

The query system is complex enough for me to not be comfortable approving this. My thoughts:

  • we should probably change the type_of query to ICE if opt_const_param_of returns Some. Or actually, we should remove the opt_const_param_of query entirely and put the branches from there into type_of and ICE for branches which would result in Some.
  • doing that should change the buggy behavior when not using feed from query cycle to ICE (with a good message). So I am not that concerned about the impact on other rustc devs using type_of, especially compared to understanding WithOptConstParam which is a lot more involved.
  • being feedable should be opt-in, as mentioned by @bjorn3. We should probably even change it so that queries are either feedable or provided. For that we would have to split type_of into type_of and anon_const_type or whatever 🤔
  • if we have type_of calling another query which then feeds the value of type_of (which is currently getting computed), we should ICE I think? I don't think this is currently covered, but haven't looked into the query impl too much ^^

going to hand off this review to incr comp people, but I am looking forward to this PR landing. I do think it requires an MCP though.

r? @wesleywiser maybe, @michaelwoerister isn't available much rn afaict

@cjgillot
Copy link
Contributor Author

cjgillot commented Sep 5, 2022

* we should probably change the `type_of` query to ICE if `opt_const_param_of` returns `Some`. Or actually, we should remove the `opt_const_param_of` query entirely and put the branches from there into `type_of` and ICE for branches which would result in `Some`.

This is not really possible yet. I could remove the case where tcx.typeck was invoked, but other uses remain. For instance, types in signatures cannot be dealt with that way, because const_evaluatable_predicates_of needs them.

* doing that should change the buggy behavior when not using `feed` from query cycle to ICE (with a good message). So I am not that concerned about the impact on other rustc devs using `type_of`, especially compared to understanding `WithOptConstParam` which is a lot more involved.

Mmh... I wonder where to put this message. Do you have an example of such misuse?

* being feedable should be opt-in, as mentioned by @bjorn3. We should probably even change it so that queries are either feedable or provided. For that we would have to split `type_of` into `type_of` and `anon_const_type` or whatever thinking

Done.

* if we have `type_of` calling another query which then feeds the value of `type_of` (which is currently getting computed), we should ICE I think? I don't think this is currently covered, but haven't looked into the query impl too much ^^

We do not ICE, we check that both values' fingerprints match.

@cjgillot cjgillot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 5, 2022
@cjgillot
Copy link
Contributor Author

cjgillot commented Sep 5, 2022

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 5, 2022
@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 20, 2023
@cjgillot
Copy link
Contributor Author

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented Apr 21, 2023

📌 Commit 9bab866 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 21, 2023
@bors
Copy link
Contributor

bors commented Apr 21, 2023

⌛ Testing commit 9bab866 with merge 1f5768b...

@bors
Copy link
Contributor

bors commented Apr 21, 2023

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing 1f5768b to master...

1 similar comment
@bors
Copy link
Contributor

bors commented Apr 21, 2023

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing 1f5768b to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 21, 2023
@bors bors merged commit 1f5768b into rust-lang:master Apr 21, 2023
@rustbot rustbot added this to the 1.71.0 milestone Apr 21, 2023
@nbdd0121
Copy link
Contributor

// not the expected parameter type from WithOptConstParam.

One reference to WithOptConstParam remaining in the comment

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (1f5768b): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.6% [0.6%, 0.6%] 1
Improvements ✅
(primary)
-0.8% [-2.1%, -0.3%] 57
Improvements ✅
(secondary)
-0.9% [-1.7%, -0.3%] 26
All ❌✅ (primary) -0.8% [-2.1%, -0.3%] 57

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.4% [0.4%, 0.4%] 1
Regressions ❌
(secondary)
4.4% [1.4%, 9.3%] 4
Improvements ✅
(primary)
-5.7% [-12.0%, -0.4%] 8
Improvements ✅
(secondary)
-3.3% [-4.4%, -2.2%] 6
All ❌✅ (primary) -5.0% [-12.0%, 0.4%] 9

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
2.5% [2.3%, 2.7%] 2
Improvements ✅
(primary)
-2.4% [-5.1%, -1.0%] 14
Improvements ✅
(secondary)
-2.2% [-2.3%, -2.2%] 2
All ❌✅ (primary) -2.4% [-5.1%, -1.0%] 14

jyn514 added a commit to jyn514/rust that referenced this pull request Apr 26, 2023
Add regression tests for const-generic inherent associated types

Fixes rust-lang#109759.
The tests are no longer failing since rust-lang#96840 which was merged recently (rust-lang#109410 is no longer necessary for them).

`@rustbot` label F-inherent_associated_types
flip1995 pushed a commit to flip1995/rust that referenced this pull request May 5, 2023
Allow to feed a value in another query's cache and remove `WithOptConstParam`

I used it to remove `WithOptConstParam` queries, as an example.

The idea is that a query (here `typeck(function)`) can write into another query's cache (here `type_of(anon const)`). The dependency node for `type_of` would depend on all the current dependencies of `typeck`.

There is still an issue with cycles: if `type_of(anon const)` is accessed before `typeck(function)`, we will still have the usual cycle.  The way around this issue is to `ensure` that `typeck(function)` is called before accessing `type_of(anon const)`.

When replayed, we may the following cases:
- `typeck` is green, in that case `type_of` is green too, and all is right;
- `type_of` is green, `typeck` may still be marked as red (it depends on strictly more things than `type_of`) -> we verify that the saved value and the re-computed value of `type_of` have the same hash;
- `type_of` is red, then `typeck` is red -> it's the caller responsibility to ensure `typeck` is recomputed *before* `type_of`.

As `anon consts` have their own `DefPathData`, it's not possible to have the def-id of the anon-const point to something outside the original function, but the general case may have to be resolved before using this device more broadly.

There is an open question about loading from the on-disk cache.  If `typeck` is loaded from the on-disk cache, the side-effect does not happen. The regular `type_of` implementation can go and fetch the correct value from the decoded `typeck` results, and the dep-graph will check that the hashes match, but I'm not sure we want to rely on this behaviour.

I specifically allowed to feed the value to `type_of` from inside a call to `type_of`.  In that case, the dep-graph will check that the fingerprints of both values match.

This implementation is still very sensitive to cycles, and requires that we call `typeck(function)` before `typeck(anon const)`.  The reason is that `typeck(anon const)` calls `type_of(anon const)`, which calls `typeck(function)`, which feeds `type_of(anon const)`, and needs to build the MIR so needs `typeck(anon const)`.  The latter call would not cycle, since `type_of(anon const)` has been set, but I'd rather not remove the cycle check.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.