Rollup merge of #153326 - Zalathar:query-modifiers, r=nnethercote

Make `rustc_with_all_queries!` pass query modifiers as named values

This PR is a bold overhaul of how the proc-macro in `rustc_macros::query` passes query modifiers to the callback macros in `rustc_middle` and `rustc_query_impl`.

The existing approach passes modifiers as a list that looks like `[(arena_cache), (no_hash)]`. That style requires a family of helper macros (`if_arena_cache!`, `if_no_hash!`) to check for modifiers when consuming the query list.

This PR changes the proc-macro to instead pass modifiers like this:

```text
{
    anon: false,
    arena_cache: true,
    cache_on_disk: false,
    ...
}
```

This style allows each of the callback macros to deconstruct the modifier list in a relatively straightforward way, by binding the true/false literals to variables like `$arena_cache:literal`.

One of the big advantages of this style is that we can write things like `#[cfg($arena_cache)]` and `#[cfg(not($arena_cache))]` to select blocks of code, eliminating the need for the `if_arena_cache!` family of helper macros.

In follow-up PRs, we can also try to take advantage of the new modifier style to pass richer information for some modifiers, such as `desc` or `cache_on_disk_if`. That could potentially make it more reasonable to get rid of the `_description_fns` and `_cache_on_disk_if_fns` modules, as proposed in https://github.com/rust-lang/rust/pull/153065.

r? nnethercote
This commit is contained in:
Jonathan Brouwer
2026-03-03 13:08:46 +01:00
committed by GitHub
5 changed files with 260 additions and 372 deletions
+77 -84
View File
@@ -137,54 +137,23 @@ struct CacheOnDiskIf {
block: Block,
}
/// See `rustc_middle::query::modifiers` for documentation of each query modifier.
struct QueryModifiers {
/// The description of the query.
desc: Desc,
/// Use this type for the in-memory cache.
arena_cache: Option<Ident>,
/// Cache the query to disk if the `Block` returns true.
cache_on_disk_if: Option<CacheOnDiskIf>,
/// A cycle error for this query aborting the compilation with a fatal error.
cycle_fatal: Option<Ident>,
/// A cycle error results in a delay_bug call
cycle_delay_bug: Option<Ident>,
/// A cycle error results in a stashed cycle error that can be unstashed and canceled later
cycle_stash: Option<Ident>,
/// Don't hash the result, instead just mark a query red if it runs
no_hash: Option<Ident>,
/// Generate a dep node based on the dependencies of the query
// tidy-alphabetical-start
anon: Option<Ident>,
/// Always evaluate the query, ignoring its dependencies
eval_always: Option<Ident>,
/// Whether the query has a call depth limit
arena_cache: Option<Ident>,
cache_on_disk_if: Option<CacheOnDiskIf>,
cycle_delay_bug: Option<Ident>,
cycle_fatal: Option<Ident>,
cycle_stash: Option<Ident>,
depth_limit: Option<Ident>,
/// Use a separate query provider for local and extern crates
separate_provide_extern: Option<Ident>,
/// Generate a `feed` method to set the query's value from another query.
desc: Desc,
eval_always: Option<Ident>,
feedable: Option<Ident>,
/// When this query is called via `tcx.ensure_ok()`, it returns
/// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to
/// be executed, and that execution returns an error, the error result is
/// returned to the caller.
///
/// If execution is skipped, a synthetic `Ok(())` is returned, on the
/// assumption that a query with all-green inputs must have succeeded.
///
/// Can only be applied to queries with a return value of
/// `Result<_, ErrorGuaranteed>`.
no_hash: Option<Ident>,
return_result_from_ensure_ok: Option<Ident>,
separate_provide_extern: Option<Ident>,
// tidy-alphabetical-end
}
fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
@@ -272,6 +241,68 @@ macro_rules! try_insert {
})
}
fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macro2::TokenStream {
let QueryModifiers {
// tidy-alphabetical-start
anon,
arena_cache,
cache_on_disk_if,
cycle_delay_bug,
cycle_fatal,
cycle_stash,
depth_limit,
desc: _,
eval_always,
feedable,
no_hash,
return_result_from_ensure_ok,
separate_provide_extern,
// tidy-alphabetical-end
} = modifiers;
let anon = anon.is_some();
let arena_cache = arena_cache.is_some();
let cache_on_disk = cache_on_disk_if.is_some();
let cycle_error_handling = if cycle_delay_bug.is_some() {
quote! { DelayBug }
} else if cycle_fatal.is_some() {
quote! { Fatal }
} else if cycle_stash.is_some() {
quote! { Stash }
} else {
quote! { Error }
};
let depth_limit = depth_limit.is_some();
let eval_always = eval_always.is_some();
let feedable = feedable.is_some();
let no_hash = no_hash.is_some();
let return_result_from_ensure_ok = return_result_from_ensure_ok.is_some();
let separate_provide_extern = separate_provide_extern.is_some();
// Giving an input span to the modifier names in the modifier list seems
// to give slightly more helpful errors when one of the callback macros
// fails to parse the modifier list.
let query_name_span = query.name.span();
quote_spanned! {
query_name_span =>
// Search for (QMODLIST) to find all occurrences of this query modifier list.
// tidy-alphabetical-start
anon: #anon,
arena_cache: #arena_cache,
cache_on_disk: #cache_on_disk,
cycle_error_handling: #cycle_error_handling,
depth_limit: #depth_limit,
eval_always: #eval_always,
feedable: #feedable,
no_hash: #no_hash,
return_result_from_ensure_ok: #return_result_from_ensure_ok,
separate_provide_extern: #separate_provide_extern,
// tidy-alphabetical-end
}
}
fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attribute> {
use ::syn::*;
let mut iter = list.iter();
@@ -458,51 +489,13 @@ macro_rules! assert {
ReturnType::Type(..) => quote! { #return_ty },
};
let mut modifiers_out = vec![];
macro_rules! passthrough {
( $( $modifier:ident ),+ $(,)? ) => {
$( if let Some($modifier) = &modifiers.$modifier {
modifiers_out.push(quote! { (#$modifier) });
}; )+
}
}
passthrough!(
arena_cache,
cycle_fatal,
cycle_delay_bug,
cycle_stash,
no_hash,
anon,
eval_always,
feedable,
depth_limit,
separate_provide_extern,
return_result_from_ensure_ok,
);
// If there was a `cache_on_disk_if` modifier in the real input, pass
// on a synthetic `(cache_on_disk)` modifier that can be inspected by
// macro-rules macros.
if modifiers.cache_on_disk_if.is_some() {
modifiers_out.push(quote! { (cache_on_disk) });
}
// This uses the span of the query definition for the commas,
// which can be important if we later encounter any ambiguity
// errors with any of the numerous macro_rules! macros that
// we use. Using the call-site span would result in a span pointing
// at the entire `rustc_queries!` invocation, which wouldn't
// be very useful.
let span = name.span();
let modifiers_stream = quote_spanned! { span => #(#modifiers_out),* };
let modifiers_stream = make_modifiers_stream(&query, modifiers);
// Add the query to the group
query_stream.extend(quote! {
#(#doc_comments)*
[#modifiers_stream]
fn #name(#key_ty) #return_ty,
fn #name(#key_ty) #return_ty
{ #modifiers_stream }
});
if let Some(feedable) = &modifiers.feedable {
@@ -268,8 +268,10 @@ macro_rules! define_dep_nodes {
queries {
$(
$(#[$q_attr:meta])*
[$($modifiers:tt)*]
fn $q_name:ident($K:ty) -> $V:ty,
fn $q_name:ident($K:ty) -> $V:ty
// Search for (QMODLIST) to find all occurrences of this query modifier list.
// Query modifiers are currently not used here, so skip the whole list.
{ $($modifiers:tt)* }
)*
}
non_queries {
+93 -117
View File
@@ -333,44 +333,6 @@ macro_rules! query_helper_param_ty {
($K:ty) => { $K };
}
// Expands to `$yes` if the `arena_cache` modifier is present, `$no` otherwise.
macro_rules! if_arena_cache {
([] $then:tt $no:tt) => { $no };
([(arena_cache) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_arena_cache!([$($modifiers)*] $yes $no)
};
}
// Expands to `$yes` if the `separate_provide_extern` modifier is present, `$no` otherwise.
macro_rules! if_separate_provide_extern {
([] $then:tt $no:tt) => { $no };
([(separate_provide_extern) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_separate_provide_extern!([$($modifiers)*] $yes $no)
};
}
// Expands to `$yes` if the `return_result_from_ensure_ok` modifier is present, `$no` otherwise.
macro_rules! if_return_result_from_ensure_ok {
([] $then:tt $no:tt) => { $no };
([(return_result_from_ensure_ok) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_return_result_from_ensure_ok!([$($modifiers)*] $yes $no)
};
}
// Expands to `$item` if the `feedable` modifier is present.
macro_rules! item_if_feedable {
([] $($item:tt)*) => {};
([(feedable) $($rest:tt)*] $($item:tt)*) => {
$($item)*
};
([$other:tt $($modifiers:tt)*] $($item:tt)*) => {
item_if_feedable! { [$($modifiers)*] $($item)* }
};
}
macro_rules! define_callbacks {
(
// You might expect the key to be `$K:ty`, but it needs to be `$($K:tt)*` so that
@@ -378,8 +340,20 @@ macro_rules! define_callbacks {
queries {
$(
$(#[$attr:meta])*
[$($modifiers:tt)*]
fn $name:ident($($K:tt)*) -> $V:ty,
fn $name:ident($($K:tt)*) -> $V:ty
{
// Search for (QMODLIST) to find all occurrences of this query modifier list.
anon: $anon:literal,
arena_cache: $arena_cache:literal,
cache_on_disk: $cache_on_disk:literal,
cycle_error_handling: $cycle_error_handling:ident,
depth_limit: $depth_limit:literal,
eval_always: $eval_always:literal,
feedable: $feedable:literal,
no_hash: $no_hash:literal,
return_result_from_ensure_ok: $return_result_from_ensure_ok:literal,
separate_provide_extern: $separate_provide_extern:literal,
}
)*
}
// Non-queries are unused here.
@@ -394,20 +368,31 @@ pub mod $name {
pub type Key<'tcx> = $($K)*;
pub type Value<'tcx> = $V;
pub type LocalKey<'tcx> = if_separate_provide_extern!(
[$($modifiers)*]
(<Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey)
(Key<'tcx>)
);
/// Key type used by provider functions in `local_providers`.
/// This query has the `separate_provide_extern` modifier.
#[cfg($separate_provide_extern)]
pub type LocalKey<'tcx> =
<Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey;
/// Key type used by provider functions in `local_providers`.
#[cfg(not($separate_provide_extern))]
pub type LocalKey<'tcx> = Key<'tcx>;
/// This type alias specifies the type returned from query providers and the type
/// used for decoding. For regular queries this is the declared returned type `V`,
/// but `arena_cache` will use `<V as ArenaCached>::Provided` instead.
pub type ProvidedValue<'tcx> = if_arena_cache!(
[$($modifiers)*]
(<Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided)
(Value<'tcx>)
);
/// Return type of the `.ensure_ok()` method for this query,
/// which has the `return_result_from_ensure_ok` modifier.
#[cfg($return_result_from_ensure_ok)]
pub type EnsureOkReturnType = Result<(), rustc_errors::ErrorGuaranteed>;
/// Return type of the `.ensure_ok()` method for this query,
/// which does _not_ have the `return_result_from_ensure_ok` modifier.
#[cfg(not($return_result_from_ensure_ok))]
pub type EnsureOkReturnType = ();
/// Type returned from query providers and loaded from disk-cache.
#[cfg($arena_cache)]
pub type ProvidedValue<'tcx> =
<Value<'tcx> as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided;
/// Type returned from query providers and loaded from disk-cache.
#[cfg(not($arena_cache))]
pub type ProvidedValue<'tcx> = Value<'tcx>;
/// This helper function takes a value returned by the query provider
/// (or loaded from disk, or supplied by query feeding), allocates
@@ -420,23 +405,23 @@ pub fn provided_to_erased<'tcx>(
) -> Erased<Value<'tcx>> {
// For queries with the `arena_cache` modifier, store the
// provided value in an arena and get a reference to it.
let value: Value<'tcx> = if_arena_cache!(
[$($modifiers)*]
{
<Value<'tcx> as $crate::query::arena_cached::ArenaCached>::
alloc_in_arena
(
tcx,
&tcx.query_system.arenas.$name,
provided_value,
)
}
{
// Otherwise, the provided value is the value (and `tcx` is unused).
let _ = tcx;
provided_value
}
);
#[cfg($arena_cache)]
let value: Value<'tcx> = {
use $crate::query::arena_cached::ArenaCached;
<Value<'tcx> as ArenaCached>::alloc_in_arena(
tcx,
&tcx.query_system.arenas.$name,
provided_value,
)
};
// Otherwise, the provided value is the value (and `tcx` is unused).
#[cfg(not($arena_cache))]
let value: Value<'tcx> = {
let _ = tcx;
provided_value
};
erase::erase_val(value)
}
@@ -480,13 +465,11 @@ pub fn provided_to_erased<'tcx>(
#[derive(Default)]
pub struct QueryArenas<'tcx> {
$(
pub $name: if_arena_cache!(
[$($modifiers)*]
// Use the `ArenaCached` helper trait to determine the arena's value type.
(TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>)
// No arena for this query, so the field type is `()`.
()
),
// Use the `ArenaCached` helper trait to determine the arena's value type.
#[cfg($arena_cache)]
pub $name: TypedArena<
<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated,
>,
)*
}
@@ -497,16 +480,14 @@ impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> {
pub fn $name(
self,
key: query_helper_param_ty!($($K)*),
) -> if_return_result_from_ensure_ok!(
[$($modifiers)*]
(Result<(), ErrorGuaranteed>)
()
) {
if_return_result_from_ensure_ok!(
[$($modifiers)*]
(crate::query::inner::query_ensure_error_guaranteed)
(crate::query::inner::query_ensure)
)(
) -> $crate::queries::$name::EnsureOkReturnType {
#[cfg($return_result_from_ensure_ok)]
let ensure_fn = crate::query::inner::query_ensure_error_guaranteed;
#[cfg(not($return_result_from_ensure_ok))]
let ensure_fn = crate::query::inner::query_ensure;
ensure_fn(
self.tcx,
&self.tcx.query_system.query_vtables.$name,
$crate::query::IntoQueryParam::into_query_param(key),
@@ -560,24 +541,22 @@ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
}
$(
item_if_feedable! {
[$($modifiers)*]
impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
TyCtxtFeed<'tcx, K>
{
$(#[$attr])*
#[inline(always)]
pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
let key = self.key().into_query_param();
let erased_value = $name::provided_to_erased(self.tcx, value);
$crate::query::inner::query_feed(
self.tcx,
dep_graph::DepKind::$name,
&self.tcx.query_system.query_vtables.$name,
key,
erased_value,
);
}
#[cfg($feedable)]
impl<'tcx, K: $crate::query::IntoQueryParam<$name::Key<'tcx>> + Copy>
TyCtxtFeed<'tcx, K>
{
$(#[$attr])*
#[inline(always)]
pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
let key = self.key().into_query_param();
let erased_value = $name::provided_to_erased(self.tcx, value);
$crate::query::inner::query_feed(
self.tcx,
dep_graph::DepKind::$name,
&self.tcx.query_system.query_vtables.$name,
key,
erased_value,
);
}
}
)*
@@ -602,11 +581,11 @@ pub struct Providers {
pub struct ExternProviders {
$(
pub $name: if_separate_provide_extern!(
[$($modifiers)*]
(for<'tcx> fn(TyCtxt<'tcx>, $name::Key<'tcx>) -> $name::ProvidedValue<'tcx>)
()
),
#[cfg($separate_provide_extern)]
pub $name: for<'tcx> fn(
TyCtxt<'tcx>,
$name::Key<'tcx>,
) -> $name::ProvidedValue<'tcx>,
)*
}
@@ -626,13 +605,10 @@ impl Default for ExternProviders {
fn default() -> Self {
ExternProviders {
$(
$name: if_separate_provide_extern!(
[$($modifiers)*]
(|_, key| $crate::query::plumbing::default_extern_query(
stringify!($name),
&key
))
()
#[cfg($separate_provide_extern)]
$name: |_, key| $crate::query::plumbing::default_extern_query(
stringify!($name),
&key,
),
)*
}
@@ -130,8 +130,20 @@ macro_rules! define_dep_kind_vtables {
queries {
$(
$(#[$attr:meta])*
[$($modifiers:tt)*]
fn $name:ident($K:ty) -> $V:ty,
fn $name:ident($K:ty) -> $V:ty
{
// Search for (QMODLIST) to find all occurrences of this query modifier list.
anon: $anon:literal,
arena_cache: $arena_cache:literal,
cache_on_disk: $cache_on_disk:literal,
cycle_error_handling: $cycle_error_handling:ident,
depth_limit: $depth_limit:literal,
eval_always: $eval_always:literal,
feedable: $feedable:literal,
no_hash: $no_hash:literal,
return_result_from_ensure_ok: $return_result_from_ensure_ok:literal,
separate_provide_extern: $separate_provide_extern:literal,
}
)*
}
non_queries {
@@ -154,9 +166,9 @@ fn $name:ident($K:ty) -> $V:ty,
$crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
$crate::query_impl::$name::VTableGetter,
>(
is_anon!([$($modifiers)*]),
if_cache_on_disk!([$($modifiers)*] true false),
is_eval_always!([$($modifiers)*]),
$anon,
$cache_on_disk,
$eval_always,
)
),*
];
+69 -164
View File
@@ -99,125 +99,6 @@ pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> boo
tcx.dep_graph.try_mark_green(tcx, dep_node).is_some()
}
macro_rules! cycle_error_handling {
([]) => {{
rustc_middle::query::CycleErrorHandling::Error
}};
([(cycle_fatal) $($rest:tt)*]) => {{
rustc_middle::query::CycleErrorHandling::Fatal
}};
([(cycle_stash) $($rest:tt)*]) => {{
rustc_middle::query::CycleErrorHandling::Stash
}};
([(cycle_delay_bug) $($rest:tt)*]) => {{
rustc_middle::query::CycleErrorHandling::DelayBug
}};
([$other:tt $($modifiers:tt)*]) => {
cycle_error_handling!([$($modifiers)*])
};
}
macro_rules! is_anon {
([]) => {{
false
}};
([(anon) $($rest:tt)*]) => {{
true
}};
([$other:tt $($modifiers:tt)*]) => {
is_anon!([$($modifiers)*])
};
}
macro_rules! is_eval_always {
([]) => {{
false
}};
([(eval_always) $($rest:tt)*]) => {{
true
}};
([$other:tt $($modifiers:tt)*]) => {
is_eval_always!([$($modifiers)*])
};
}
macro_rules! is_depth_limit {
([]) => {{
false
}};
([(depth_limit) $($rest:tt)*]) => {{
true
}};
([$other:tt $($modifiers:tt)*]) => {
is_depth_limit!([$($modifiers)*])
};
}
macro_rules! is_feedable {
([]) => {{
false
}};
([(feedable) $($rest:tt)*]) => {{
true
}};
([$other:tt $($modifiers:tt)*]) => {
is_feedable!([$($modifiers)*])
};
}
/// Expands to `$yes` if the `no_hash` modifier is present, or `$no` otherwise.
macro_rules! if_no_hash {
([] $yes:tt $no:tt) => { $no };
([(no_hash) $($modifiers:tt)*] $yes:tt $no:tt) => { $yes };
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_no_hash!([$($modifiers)*] $yes $no)
}
}
macro_rules! call_provider {
([][$tcx:expr, $name:ident, $key:expr]) => {{
($tcx.query_system.local_providers.$name)($tcx, $key)
}};
([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{
if let Some(key) = $key.as_local_key() {
($tcx.query_system.local_providers.$name)($tcx, key)
} else {
($tcx.query_system.extern_providers.$name)($tcx, $key)
}
}};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
call_provider!([$($modifiers)*][$($args)*])
};
}
/// Expands to one of two token trees, depending on whether the current query
/// has the `cache_on_disk_if` modifier.
macro_rules! if_cache_on_disk {
([] $yes:tt $no:tt) => {
$no
};
// The `cache_on_disk_if` modifier generates a synthetic `(cache_on_disk)`,
// modifier, for use by this macro and similar macros.
([(cache_on_disk) $($rest:tt)*] $yes:tt $no:tt) => {
$yes
};
([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => {
if_cache_on_disk!([$($modifiers)*] $yes $no)
};
}
/// Conditionally expands to some token trees, if the current query has the
/// `cache_on_disk_if` modifier.
macro_rules! item_if_cache_on_disk {
([] $($item:tt)*) => {};
([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => {
$($item)*
};
([$other:tt $($modifiers:tt)*] $($item:tt)*) => {
item_if_cache_on_disk! { [$($modifiers)*] $($item)* }
};
}
/// The deferred part of a deferred query stack frame.
fn mk_query_stack_frame_extra<'tcx, Cache>(
(tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key),
@@ -421,8 +302,20 @@ macro_rules! define_queries {
queries {
$(
$(#[$attr:meta])*
[$($modifiers:tt)*]
fn $name:ident($K:ty) -> $V:ty,
fn $name:ident($K:ty) -> $V:ty
{
// Search for (QMODLIST) to find all occurrences of this query modifier list.
anon: $anon:literal,
arena_cache: $arena_cache:literal,
cache_on_disk: $cache_on_disk:literal,
cycle_error_handling: $cycle_error_handling:ident,
depth_limit: $depth_limit:literal,
eval_always: $eval_always:literal,
feedable: $feedable:literal,
no_hash: $no_hash:literal,
return_result_from_ensure_ok: $return_result_from_ensure_ok:literal,
separate_provide_extern: $separate_provide_extern:literal,
}
)*
}
// Non-queries are unused here.
@@ -498,7 +391,16 @@ pub(crate) fn __rust_begin_short_backtrace<'tcx>(
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
// Call the actual provider function for this query.
let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]);
#[cfg($separate_provide_extern)]
let provided_value = if let Some(local_key) = key.as_local_key() {
(tcx.query_system.local_providers.$name)(tcx, local_key)
} else {
(tcx.query_system.extern_providers.$name)(tcx, key)
};
#[cfg(not($separate_provide_extern))]
let provided_value = (tcx.query_system.local_providers.$name)(tcx, key);
rustc_middle::ty::print::with_reduced_queries!({
tracing::trace!(?provided_value);
@@ -515,64 +417,67 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
{
QueryVTable {
name: stringify!($name),
anon: is_anon!([$($modifiers)*]),
eval_always: is_eval_always!([$($modifiers)*]),
depth_limit: is_depth_limit!([$($modifiers)*]),
feedable: is_feedable!([$($modifiers)*]),
anon: $anon,
eval_always: $eval_always,
depth_limit: $depth_limit,
feedable: $feedable,
dep_kind: dep_graph::DepKind::$name,
cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
cycle_error_handling:
rustc_middle::query::CycleErrorHandling::$cycle_error_handling,
state: Default::default(),
cache: Default::default(),
will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] {
Some(::rustc_middle::queries::_cache_on_disk_if_fns::$name)
} {
None
}),
#[cfg($cache_on_disk)]
will_cache_on_disk_for_key_fn:
Some(rustc_middle::queries::_cache_on_disk_if_fns::$name),
#[cfg(not($cache_on_disk))]
will_cache_on_disk_for_key_fn: None,
call_query_method_fn: |tcx, key| {
// Call the query method for its side-effect of loading a value
// from disk-cache; the caller doesn't need the value.
let _ = tcx.$name(key);
},
invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace,
try_load_from_disk_fn: if_cache_on_disk!([$($modifiers)*] {
Some(|tcx, key, prev_index, index| {
// Check the `cache_on_disk_if` condition for this key.
if !::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) {
return None;
}
let value: queries::$name::ProvidedValue<'tcx> =
$crate::plumbing::try_load_from_disk(tcx, prev_index, index)?;
#[cfg($cache_on_disk)]
try_load_from_disk_fn: Some(|tcx, key, prev_index, index| {
// Check the `cache_on_disk_if` condition for this key.
if !rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) {
return None;
}
// Arena-alloc the value if appropriate, and erase it.
Some(queries::$name::provided_to_erased(tcx, value))
})
} {
None
let value: queries::$name::ProvidedValue<'tcx> =
$crate::plumbing::try_load_from_disk(tcx, prev_index, index)?;
// Arena-alloc the value if appropriate, and erase it.
Some(queries::$name::provided_to_erased(tcx, value))
}),
is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] {
Some(|tcx, key, index| -> bool {
::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) &&
$crate::plumbing::loadable_from_disk(tcx, index)
})
} {
None
#[cfg(not($cache_on_disk))]
try_load_from_disk_fn: None,
#[cfg($cache_on_disk)]
is_loadable_from_disk_fn: Some(|tcx, key, index| -> bool {
rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) &&
$crate::plumbing::loadable_from_disk(tcx, index)
}),
#[cfg(not($cache_on_disk))]
is_loadable_from_disk_fn: None,
value_from_cycle_error: |tcx, cycle, guar| {
let result: queries::$name::Value<'tcx> =
FromCycleError::from_cycle_error(tcx, cycle, guar);
erase::erase_val(result)
},
hash_value_fn: if_no_hash!(
[$($modifiers)*]
None
{
Some(|hcx, erased_value: &erase::Erased<queries::$name::Value<'tcx>>| {
let value = erase::restore_val(*erased_value);
rustc_middle::dep_graph::hash_result(hcx, &value)
})
}
),
#[cfg($no_hash)]
hash_value_fn: None,
#[cfg(not($no_hash))]
hash_value_fn: Some(|hcx, erased_value: &erase::Erased<queries::$name::Value<'tcx>>| {
let value = erase::restore_val(*erased_value);
rustc_middle::dep_graph::hash_result(hcx, &value)
}),
format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
description_fn: $crate::queries::_description_fns::$name,
execute_query_fn: if incremental {
@@ -670,8 +575,8 @@ fn encode_all_query_results<'tcx>(
query_result_index: &mut EncodedDepNodeIndex,
) {
$(
item_if_cache_on_disk! {
[$($modifiers)*]
#[cfg($cache_on_disk)]
{
$crate::plumbing::encode_query_results(
tcx,
&tcx.query_system.query_vtables.$name,