This effectively reverses <https://github.com/rust-lang/rust/commit/4284edc>.
At that time, I thought GetQueryVTable might be useful for other kinds of
static lookup in the future, but after various other simplifications and
cleanups that now seems less likely, and this style is more consistent with
other vtable-related functions.
The different parts of this function used to be split across different crates,
but nowadays they are both in `rustc_query_impl`, so they can be combined.
This commit also hoists the vtable lookup to a closure in
`make_dep_kind_vtable_for_query`, to reduce the amount of code that deals with
`GetQueryVTable`, and to make the inner function more consistent with other
functions in `execution`.
In the serial compiler, we should never be trying to force a query node that
has a cached value, because we would have already marked the node red or green
when putting its value in cache.
In the parallel compiler, we immediately re-check the cache while holding the
state shard lock anyway, and trying to avoid that lock doesn't seem worthwhile.
This assertion and its comment are much visually heavier than the part of the
function that actually performs important work.
This assertion is also useless, because the `codegen_unit` query does not have
a `force_from_dep_node_fn` in its DepKindVTable, so the assertion would never
be reached even in the situation it is trying to guard against.
This assertion is also redundant, because we have plenty of incremental tests
that fail if the corresponding calls to `tcx.ensure_ok().codegen_unit(..)` are
removed.
These queries appear to have been using `anon` for its side-effect of making
them ineligible for forcing.
According to their comments and also `tests/incremental/issue-61323.rs`, these
queries want to avoid forcing so that if a cycle does occur, the whole cycle
will be on the query stack for the cycle handler to find.
Code that previously used `QueryStackFrame` now uses `TaggedQueryKey` directly.
Code that previously used `Spanned<QueryStackFrame>` now uses
`QueryStackFrame`, which includes a span.
variances_of currently used search_for_cycle_permutation, which can fail and abort when constructed error result value does not match query input.
This commit changes variances_of to receive a def_id which means it can compute a value without using search_for_cycle_permutation, avoiding the possible abort.
Fixes#127971
An explicit dep-kind is redundant here. If we want to find the query name, or
check for specific queries, we can inspect the `TaggedQueryKey` instead.
Similarly, in cases where the key is some kind of `DefId`, we can extract it
directly from the `TaggedQueryKey`.
Re-export `rustc_middle::query::{QuerySystem, QueryVTable}`
- Follow-up to https://github.com/rust-lang/rust/pull/153760#discussion_r2928848418.
---
All of the other public items in `rustc_middle::query::plumbing` are re-exported from `query`, except for these two, for no particular reason that I can see.
Re-exporting them allows `rustc_middle::query::plumbing` to have its visibility reduced to pub(crate).
Imports within `rustc_middle` have also been updated to consistently use the re-exports in `crate::query`.
r? nnethercote
Rename all-query functions.
There are four functions that use `for_each_query_vtable!` to call an "inner" function. They are:
- `collect_active_jobs_from_all_queries` -> `gather_active_jobs`
- `alloc_self_profile_query_strings` -> `alloc_self_profile_query_strings_for_query_cache`
- `encode_all_query_results` -> `encode_query_results`
- `query_key_hash_verify_all` -> `query_key_hash_verify`
These names are all over the place. This commit renames them as follows:
- `collect_active_query_jobs{,_inner}`
- `alloc_self_profile_query_strings{,_inner}`
- `encode_query_values{,_inner}`
- `verify_query_key_hashes{,_inner}`
This:
- puts the verb at the start
- uses `_inner` for all the inners (which makes sense now that the inners are all next to their callers)
- uses `_query_` consistently
- avoids `all`, because the plurals are enough
- uses `values` instead of `results`
- removes the `collect`/`gather` distinction, which is no longer important
r? @Zalathar
All of the other public items in `rustc_middle::query::plumbing` are
re-exported from `query`, except for these two, for no particular reason that I
can see.
Re-exporting them allows `rustc_middle::query::plumbing` to have its visibility
reduced to pub(crate).
Imports within `rustc_middle` have also been updated to consistently use the
re-exports in `crate::query`.
There are four functions that use `for_each_query_vtable!` to call an "inner"
function. They are:
- collect_active_jobs_from_all_queries -> gather_active_jobs
- alloc_self_profile_query_strings -> alloc_self_profile_query_strings_for_query_cache
- encode_all_query_results -> encode_query_results
- query_key_hash_verify_all -> query_key_hash_verify
These names are all over the place. This commit renames them as follows:
- collect_active_query_jobs{,_inner}
- alloc_self_profile_query_strings{,_inner}
- encode_query_values{,_inner}
- verify_query_key_hashes{,_inner}
This:
- puts the verb at the start
- uses "inner" for all the inners (which makes sense now that the inners are
all next to their callers)
- uses `_query_` consistently
- avoids `all`, because the plurals are enough
- uses `values` instead of `results`
- removes the `collect`/`gather` distinction, which is no longer
important
`CycleError` has one field containing a `(Span, QueryStackFrame<I>)` and
another field containing a `QueryInfo`, which is a struct containing
just a `Span` and a `QueryStackFrame<I>`.
We already have the `Spanned` type for adding a span to something. This
commit uses it for both fields in `CycleError`, removing the need for
`QueryInfo`. Which is good for the following reasons.
- Any type with `Info` in the name is suspect, IMO.
- `QueryInfo` can no longer be confused with the similar `QueryJobInfo`.
- The doc comment on `QueryInfo` was wrong; it didn't contain a query
key.
Use less `#[macro_use]` in the query system
Macro-rules namespacing and import/export is a bit of a nightmare in general. We can tame it a bit by avoiding `#[macro_use]` as much as possible, and instead putting a `pub(crate) use` after the macro-rules declaration to make the macro importable as a normal item.
I've split this PR into two commits. The first one should hopefully be uncontroversial, while the second commit takes the extra step of declaring `rustc_with_all_queries!` as a macros-2.0 macro, which gives much nicer import/export behaviour, at the expense of having to specify `#[rustc_macro_transparency = "semiopaque"]` to still have access to macro-rules hygiene, because the default macros-2.0 hygiene is too strict here.
There should be no change to compiler behaviour.
---
I stumbled into this while investigating some other changes, such as re-exporting `rustc_middle::query::QueryVTable` or moving the big callback macro out of `rustc_middle::query::plumbing`. I think it makes sense to make this change first, to make other module-juggling tasks easier.
r? nnethercote (or compiler)
Unlike `macro_rules!`, macros-2.0 macros have sensible item-like namespacing
and visibility by default, which avoids the need for `#[macro_export]` and
makes it easier to import the macro.
The tradeoff is having to use `#[rustc_macro_transparency = "semiopaque"]` to
still get macro-rules hygiene, because macros-2.0 hygiene is too strict here.
Remove `def_id_for_ty_in_cycle`
This removes `QueryKey::def_id_for_ty_in_cycle` and `QueryStackFrame.def_id_for_ty_in_cycle` by computing it instead from `TaggedQueryKey`.
Remove `value_from_cycle_error` specializations
This removes `value_from_cycle_error` specializations which are not involved in custom cycle error handling.
This is a step towards removing query cycle recovery.
Move and expand the big `rustc_query_impl` macro into a physical `query_impl.rs`
While looking through https://github.com/rust-lang/rust/pull/153588, I came up with a related but different change that I think resolves a lot of tension in the current module arrangement.
The core idea is that if we both define and expand the big macro in the same physical module `rustc_query_impl::query_impl`, then we no longer need to worry about where `mod query_impl` should be declared, or where its imports should go, because those questions now have simple and obvious answers.
The second commit follows up with some more changes inspired by https://github.com/rust-lang/rust/pull/153588. Those particular follow-ups are not essential to the main idea of this PR.
r? nnethercote
Replace `visit_waiters` with `abstracted_waiters_of`
This replaces `visit_waiters` which uses closures to visit waiters with `abstracted_waiters_of` which returns a list of waiters. This makes the control flow of their users a bit clearer.
Additionally `abstracted_waiters_of` includes non-query waiters unlike `visit_waiters`. This means that `connected_to_root` now considers resumable waiters from the compiler root as being connected to root, while previously only non-resumable waiters counted. This can result in some additional entry points being found. Similarly in the loop detecting entry points we now consider queries in the cycle with direct resumable waiters from the compiler root as being entry points.
When looking for entry points we now look at waiters until we found a query to populate the `EntryPoint.waiter` field instead of stopping when we determined it to be an entry point.
cc @petrochenkov @nnethercote
Moving the macro and its expansion into the same physical file resolves a lot
of tension in the current module arrangement.
Code in the macro is now free to use plain imports in the same file, and there
is no longer any question of whether `mod query_impl` should be declared inside
the macro, or surrounding a separate expansion site.
Remove `CycleErrorHandling`.
This PR removes the `cycle_*` query modifiers and `CycleErrorHandling`. Some good simplicity wins. Details in individual commits.
r? @Zalathar
Currently if a cycle error occurs the error is created, then handled
according to `CycleErrorHandling` (which comes from the
`cycle_delay_bug` query modifer, or lack thereof), and then
`value_from_cycle_error` is called.
This commit changes things so the error is created and then just passed
to `value_from_cycle_error`. This gives `value_from_cycle_error` full
control over how it's handled, eliminating the need for
`CycleErrorHandling`. This makes things simpler overall.
`collect_active_jobs_from_all_queries` takes a `require_complete` bool,
and then some callers `expect` a full map result while others allow a
partial map result. The end result is four possible combinations, but
only three of them are used/make sense.
This commit introduces `CollectActiveJobsKind`, a three-value enum that
describes the three sensible combinations, and rewrites
`collect_active_jobs_from_all_queries` around it. This makes it and its
call sites much clearer, and removes the weird `Option<()>` and
`Result<QueryJobMap, QueryJobMap>` return types.
Other changes of note.
- `active` is removed. The comment about `make_frame` is out of date,
and `create_deferred_query_stack_frame` *is* safe to call with the
query state locked.
- When shard locking failure is allowed, collection no longer stops on
the first failed shard.
Add a `TaggedQueryKey` to identify a query instance
This adds back a `TaggedQueryKey` enum which represents a query kind and the associated key. This is used to replace `QueryStackDeferred` and `QueryStackFrameExtra` and the associated lifting operation for cycle errors
This approach has a couple of benefits:
- We only run description queries when printing the query stack trace in the panic handler
- The unsafe code for `QueryStackDeferred` is removed
- Cycle handles have access to query keys, which may be handy
Some further work could be replacing `QueryStackFrame` with `TaggedQueryKey` as the extra information can be derived from it.
`execute_job` has a single call site in `try_execute_query`. This commit
inlines and removes `execute_job`, but also puts the part that checks
feedable results in its own separate function, `check_feedable`, because
it's a nicely separate piece of logic.
The big win here is that all the code dealing with the `QueryState` is
now together in `try_execute_query`: get the lock, do the lookup, drop
the lock, create the job guard, and complete the job guard. Previously
these steps were split across two functions which I found hard to
follow.
This commit purely moves code around, there are no other changes.
Introduce `for_each_query_vtable!` to move more code out of query macros
After https://github.com/rust-lang/rust/pull/153114 moved a few for-each-query functions into the big `rustc_query_impl::plumbing` macro, I have found that those functions became much harder to navigate and modify, because they no longer have access to ordinary IDE features in rust-analyzer. Even *finding* the functions is considerably harder, because a plain go-to-definition no longer works smoothly.
This PR therefore tries to move as much of that code back out of the macro as possible, with the aid of a smaller `for_each_query_vtable!` helper macro. A typical use of that macro looks like this:
```rust
for_each_query_vtable!(ALL, tcx, |query| {
query_key_hash_verify(query, tcx);
});
```
The result is an outer function consisting almost entirely of plain Rust code, with all of the usual IDE affordances expected of normal Rust code. Because it uses plain Rust syntax, it can also be formatted automatically by rustfmt.
Adding another layer of macro-defined macros is not something I propose lightly, but in this case I think the improvement is well worth it:
- The outer functions can once again be defined as “normal” Rust functions, right next to their corresponding inner functions, making navigation and modification much easier.
- The closure expression is ordinary Rust code that simply gets repeated ~300 times in the expansion, once for each query, in order to account for the variety of key/value/cache types used by different queries. Even within the closure expression, IDE features still *mostly* work, which is an improvement over the status quo.
- For future maintainers looking at the call site, the macro's effect should hopefully be pretty obvious and intuitive, reducing the need to even look at the helper macro. And the helper macro itself is largely straightforward, with its biggest complication being that it necessarily uses the `$name` metavar from the outer macro.
There should be no change to compiler behaviour.
r? nnethercote (or compiler)
Simplify `type_of_opaque`.
There is a bunch of complexity supporting the "cannot check whether the hidden type of opaque type satisfies auto traits" error that shows up in `tests/ui/impl-trait/auto-trait-leak.rs`. This is an obscure error that shows up in a single test. If we are willing to downgrade that error message to a cycle error, we can do the following.
- Simplify the `type_of_opaque` return value.
- Remove the `cycle_stash` query modifier.
- Remove the `CyclePlaceholder` type.
- Remove the `SelectionError::OpaqueTypeAutoTraitLeakageUnknown` variant.
- Remove a `FromCycleError` impl.
- Remove `report_opaque_type_auto_trait_leakage`.
- Remove the `StashKey::Cycle` variant.
- Remove the `CycleErrorHandling::Stash` variant.
That's a lot! I think this is a worthwhile trade-off.
r? @oli-obk
There is a bunch of complexity supporting the "cannot check whether the
hidden type of opaque type satisfies auto traits" error that shows up in
`tests/ui/impl-trait/auto-trait-leak.rs`. This is an obscure error that
shows up in a single test. If we are willing to downgrade that error
message to a cycle error, we can do the following.
- Simplify the `type_of_opaque` return value.
- Remove the `cycle_stash` query modifier.
- Remove the `CyclePlaceholder` type.
- Remove the `SelectionError::OpaqueTypeAutoTraitLeakageUnknown`
variant.
- Remove a `FromCycleError` impl.
- Remove `report_opaque_type_auto_trait_leakage`.
- Remove the `StashKey::Cycle` variant.
- Remove the `CycleErrorHandling::Stash` variant.
That's a lot! I think this is a worthwhile trade-off.
Eliminate `QueryLatchInfo`.
The boolean `complete` flag indicates whether the `waiters` vec is still in use, which means the `waiters` vec must be empty when `complete` is true. This is achieved by using `drain` on the waiters just after `complete` is set.
We can do better by using the type system to make invalid combinations impossible. This commit removes `complete` and puts the waiters inside an `Option`. `Some` means the query job is still active, and `None` once it is complete. And `QueryLatchInfo` is eliminated.
(The `Arc<Mutex<Option<Vec<Arc<QueryWaiter<'tcx>>>>>>` type is a mouthful, but when it's all in one place I find it easier to understand than when it's split across two types. And we can use `Option` methods like `as_ref`, `as_mut`, and `take`, which is nice.)
r? @petrochenkov