From b651ab0d6c931665b52e0b8caedcbb2ddea4991d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Mar 2026 10:55:27 +1100 Subject: [PATCH 1/4] Add a useful comment. I previously tried to remove this field because it seemed useless. --- compiler/rustc_macros/src/query.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 75be5a1686035..950f4565a3dae 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -128,6 +128,7 @@ impl Parse for List { } struct Desc { + // This ident is always `desc` but we need it for its span, for `crate::query::modifiers`. modifier: Ident, expr_list: Punctuated, } From aebce4c73f1321d6ef30dfc74d4c99ccae174c11 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 2 Apr 2026 11:24:03 +1100 Subject: [PATCH 2/4] Process query modifiers in alphabetical order everywhere. --- compiler/rustc_macros/src/query.rs | 43 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 950f4565a3dae..a44efc97dc8ff 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -149,15 +149,17 @@ struct QueryModifiers { } fn parse_query_modifiers(input: ParseStream<'_>) -> Result { + // tidy-alphabetical-start let mut arena_cache = None; let mut cache_on_disk = None; + let mut depth_limit = None; let mut desc = None; + let mut eval_always = None; + let mut feedable = None; let mut no_force = None; let mut no_hash = None; - let mut eval_always = None; - let mut depth_limit = None; let mut separate_provide_extern = None; - let mut feedable = None; + // tidy-alphabetical-end while !input.is_empty() { let modifier: Ident = input.parse()?; @@ -171,29 +173,29 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { }; } - if modifier == "desc" { + if modifier == "arena_cache" { + try_insert!(arena_cache = modifier); + } else if modifier == "cache_on_disk" { + try_insert!(cache_on_disk = modifier); + } else if modifier == "depth_limit" { + try_insert!(depth_limit = modifier); + } else if modifier == "desc" { // Parse a description modifier like: // `desc { "foo {}", tcx.item_path(key) }` let attr_content; braced!(attr_content in input); let expr_list = attr_content.parse_terminated(Expr::parse, Token![,])?; try_insert!(desc = Desc { modifier, expr_list }); - } else if modifier == "cache_on_disk" { - try_insert!(cache_on_disk = modifier); - } else if modifier == "arena_cache" { - try_insert!(arena_cache = modifier); + } else if modifier == "eval_always" { + try_insert!(eval_always = modifier); + } else if modifier == "feedable" { + try_insert!(feedable = modifier); } else if modifier == "no_force" { try_insert!(no_force = modifier); } else if modifier == "no_hash" { try_insert!(no_hash = modifier); - } else if modifier == "eval_always" { - try_insert!(eval_always = modifier); - } else if modifier == "depth_limit" { - try_insert!(depth_limit = modifier); } else if modifier == "separate_provide_extern" { try_insert!(separate_provide_extern = modifier); - } else if modifier == "feedable" { - try_insert!(feedable = modifier); } else { return Err(Error::new(modifier.span(), "unknown query modifier")); } @@ -202,15 +204,17 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { return Err(input.error("no description provided")); }; Ok(QueryModifiers { + // tidy-alphabetical-start arena_cache, cache_on_disk, + depth_limit, desc, + eval_always, + feedable, no_force, no_hash, - eval_always, - depth_limit, separate_provide_extern, - feedable, + // tidy-alphabetical-end }) } @@ -248,15 +252,18 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { // tidy-alphabetical-end } = &query.modifiers; + // tidy-alphabetical-start let arena_cache = arena_cache.is_some(); let cache_on_disk = cache_on_disk.is_some(); let depth_limit = depth_limit.is_some(); + // `desc` is not handled here let eval_always = eval_always.is_some(); let feedable = feedable.is_some(); let no_force = no_force.is_some(); let no_hash = no_hash.is_some(); let returns_error_guaranteed = returns_error_guaranteed(&query.return_ty); let separate_provide_extern = separate_provide_extern.is_some(); + // tidy-alphabetical-end // 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 @@ -269,6 +276,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { arena_cache: #arena_cache, cache_on_disk: #cache_on_disk, depth_limit: #depth_limit, + // `desc` is not handled here eval_always: #eval_always, feedable: #feedable, no_force: #no_force, @@ -367,6 +375,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke arena_cache, cache_on_disk, depth_limit, + // `desc` is handled above eval_always, feedable, no_force, From d9137667574db8fd54e0766f492ff5eff236ab44 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 16 Mar 2026 19:17:58 +1100 Subject: [PATCH 3/4] Remove the `_description_fns` module. `rustc_queries` generates a macro and two modules. One of the modules looks like this: ``` mod _description_fns { ... #[allow(unused_variables)] pub fn hir_module_items<'tcx>(tcx: TyCtxt<'tcx>, key: LocalModDefId) -> String { format!("getting HIR module items in `{}`", tcx.def_path_str(key)) } ... } ``` Members of this module are then used in `TaggedQueryKey::description`. This commit removes the `_description_fns` module entirely. For each query we now instead generate a description closure that is used instead. This closure is passed in the modifiers list. This change simplifies `rustc_queries` quite a bit. It requires adding another query modifier, but query modifiers are how other query-specific details are already passed to the declarative macros, so it's more consistent. --- compiler/rustc_macros/src/query.rs | 63 +++++-------------- compiler/rustc_middle/src/query/plumbing.rs | 4 +- .../rustc_query_impl/src/dep_kind_vtables.rs | 1 + compiler/rustc_query_impl/src/query_impl.rs | 1 + 4 files changed, 18 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index a44efc97dc8ff..6960920367ffe 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -243,7 +243,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { arena_cache, cache_on_disk, depth_limit, - desc: _, + desc, eval_always, feedable, no_force, @@ -256,7 +256,18 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { let arena_cache = arena_cache.is_some(); let cache_on_disk = cache_on_disk.is_some(); let depth_limit = depth_limit.is_some(); - // `desc` is not handled here + let desc = { + // Put a description closure in the `desc` modifier. + let key_pat = &query.key_pat; + let key_ty = &query.key_ty; + let desc_expr_list = &desc.expr_list; + quote! { + { + #[allow(unused_variables)] + |tcx: TyCtxt<'tcx>, #key_pat: #key_ty| format!(#desc_expr_list) + } + } + }; let eval_always = eval_always.is_some(); let feedable = feedable.is_some(); let no_force = no_force.is_some(); @@ -276,7 +287,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { arena_cache: #arena_cache, cache_on_disk: #cache_on_disk, depth_limit: #depth_limit, - // `desc` is not handled here + desc: #desc, eval_always: #eval_always, feedable: #feedable, no_force: #no_force, @@ -314,37 +325,6 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(tcx: TyCtxt<'tcx>, #key_pat: #key_ty) -> String { - format!(#expr_list) - } - }; - - streams.description_fns_stream.extend(quote! { - #desc - }); -} - /// Add hints for rust-analyzer fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::TokenStream) { // Add links to relevant modifiers @@ -419,7 +399,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { let mut query_stream = quote! {}; let mut non_query_stream = quote! {}; - let mut helpers = HelperTokenStreams::default(); let mut analyzer_stream = quote! {}; let mut errors = quote! {}; @@ -472,11 +451,8 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { } add_to_analyzer_stream(&query, &mut analyzer_stream); - make_helpers_for_query(&query, &mut helpers); } - let HelperTokenStreams { description_fns_stream } = helpers; - TokenStream::from(quote! { /// Higher-order macro that invokes the specified macro with (a) a list of all query /// signatures (including modifiers), and (b) a list of non-query names. This allows @@ -500,17 +476,6 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { #analyzer_stream } - /// Functions that format a human-readable description of each query - /// and its key, as specified by the `desc` query modifier. - /// - /// (The leading `_` avoids collisions with actual query names when - /// expanded in `rustc_middle::queries`, and makes this macro-generated - /// module easier to search for.) - pub mod _description_fns { - use super::*; - #description_fns_stream - } - #errors }) } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 2e1e614b8fb4c..11f66f10cd549 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -301,6 +301,7 @@ macro_rules! define_callbacks { arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, depth_limit: $depth_limit:literal, + desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, no_force: $no_force:literal, @@ -435,8 +436,7 @@ macro_rules! define_callbacks { pub fn description(&self, tcx: TyCtxt<'tcx>) -> String { let (name, description) = ty::print::with_no_queries!(match self { $( - TaggedQueryKey::$name(key) => - (stringify!($name), _description_fns::$name(tcx, *key)), + TaggedQueryKey::$name(key) => (stringify!($name), ($desc)(tcx, *key)), )* }); if tcx.sess.verbose_internals() { diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index b70fe3008cb10..e0d3575863674 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -135,6 +135,7 @@ macro_rules! define_dep_kind_vtables { arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, depth_limit: $depth_limit:literal, + desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, no_force: $no_force:literal, diff --git a/compiler/rustc_query_impl/src/query_impl.rs b/compiler/rustc_query_impl/src/query_impl.rs index 2d3dae04181e5..c1e7f3ef3cdb6 100644 --- a/compiler/rustc_query_impl/src/query_impl.rs +++ b/compiler/rustc_query_impl/src/query_impl.rs @@ -19,6 +19,7 @@ macro_rules! define_queries { arena_cache: $arena_cache:literal, cache_on_disk: $cache_on_disk:literal, depth_limit: $depth_limit:literal, + desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, no_force: $no_force:literal, From 15c6e6e0925aea95e21adad02a992f070dca0002 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Apr 2026 22:01:00 +1100 Subject: [PATCH 4/4] Add a `handle_cycle_error` query modifier. This modifier indicates that a query has a custom handler for cycles. That custom handler must be found at `rustc_query_impl::handle_cycle_error::$name`. This eliminates the need for `specialize_query_vtables`, which is the current hack to install custom handlers. It's more lines of code in total, but indicating special treatment of a query via a modifier in `queries.rs` is more consistent with how other aspects of queries are handled. --- compiler/rustc_macros/src/query.rs | 9 +++ compiler/rustc_middle/src/queries.rs | 5 ++ compiler/rustc_middle/src/query/modifiers.rs | 8 +++ compiler/rustc_middle/src/query/plumbing.rs | 1 + .../rustc_query_impl/src/dep_kind_vtables.rs | 1 + .../src/handle_cycle_error.rs | 71 +++++++++++-------- compiler/rustc_query_impl/src/lib.rs | 4 +- compiler/rustc_query_impl/src/query_impl.rs | 12 ++-- 8 files changed, 74 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 6960920367ffe..3880894572c93 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -142,6 +142,7 @@ struct QueryModifiers { desc: Desc, eval_always: Option, feedable: Option, + handle_cycle_error: Option, no_force: Option, no_hash: Option, separate_provide_extern: Option, @@ -156,6 +157,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut desc = None; let mut eval_always = None; let mut feedable = None; + let mut handle_cycle_error = None; let mut no_force = None; let mut no_hash = None; let mut separate_provide_extern = None; @@ -190,6 +192,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { try_insert!(eval_always = modifier); } else if modifier == "feedable" { try_insert!(feedable = modifier); + } else if modifier == "handle_cycle_error" { + try_insert!(handle_cycle_error = modifier); } else if modifier == "no_force" { try_insert!(no_force = modifier); } else if modifier == "no_hash" { @@ -211,6 +215,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { desc, eval_always, feedable, + handle_cycle_error, no_force, no_hash, separate_provide_extern, @@ -246,6 +251,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { desc, eval_always, feedable, + handle_cycle_error, no_force, no_hash, separate_provide_extern, @@ -270,6 +276,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { }; let eval_always = eval_always.is_some(); let feedable = feedable.is_some(); + let handle_cycle_error = handle_cycle_error.is_some(); let no_force = no_force.is_some(); let no_hash = no_hash.is_some(); let returns_error_guaranteed = returns_error_guaranteed(&query.return_ty); @@ -290,6 +297,7 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { desc: #desc, eval_always: #eval_always, feedable: #feedable, + handle_cycle_error: #handle_cycle_error, no_force: #no_force, no_hash: #no_hash, returns_error_guaranteed: #returns_error_guaranteed, @@ -358,6 +366,7 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke // `desc` is handled above eval_always, feedable, + handle_cycle_error, no_force, no_hash, separate_provide_extern, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 35e33fd2d5457..63be8a63e9f27 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -583,6 +583,7 @@ rustc_queries! { // messages about cycles that then abort.) query check_representability(key: LocalDefId) { desc { "checking if `{}` is representable", tcx.def_path_str(key) } + handle_cycle_error // We don't want recursive representability calls to be forced with // incremental compilation because, if a cycle occurs, we need the // entire cycle to be in memory for diagnostics. @@ -593,6 +594,7 @@ rustc_queries! { /// details, particularly on the modifiers. query check_representability_adt_ty(key: Ty<'tcx>) { desc { "checking if `{}` is representable", key } + handle_cycle_error no_force } @@ -1032,6 +1034,7 @@ rustc_queries! { query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { desc { "computing the variances of `{}`", tcx.def_path_str(def_id) } cache_on_disk + handle_cycle_error separate_provide_extern } @@ -1164,6 +1167,7 @@ rustc_queries! { query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { desc { "computing function signature of `{}`", tcx.def_path_str(key) } cache_on_disk + handle_cycle_error separate_provide_extern } @@ -1756,6 +1760,7 @@ rustc_queries! { ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } + handle_cycle_error } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs index 2d22a548b7351..4fd91caa94cd7 100644 --- a/compiler/rustc_middle/src/query/modifiers.rs +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -58,6 +58,14 @@ pub(crate) struct eval_always; /// Generate a `feed` method to set the query's value from another query. pub(crate) struct feedable; +/// # `handle_cycle_error` query modifier +/// +/// The default behaviour for a query cycle is to emit a cycle error and halt +/// compilation. Queries with this modifier will instead use a custom handler, +/// which must be provided at `rustc_query_impl::handle_cycle_error::$name`, +/// where `$name` is the query name. +pub(crate) struct handle_cycle_error; + /// # `no_force` query modifier /// /// Dep nodes of queries with this modifier will never be "forced" when trying diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 11f66f10cd549..6b207be245ba7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -304,6 +304,7 @@ macro_rules! define_callbacks { desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, + handle_cycle_error: $handle_cycle_error:literal, no_force: $no_force:literal, no_hash: $no_hash:literal, returns_error_guaranteed: $returns_error_guaranteed:literal, diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index e0d3575863674..d12db3784f711 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -138,6 +138,7 @@ macro_rules! define_dep_kind_vtables { desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, + handle_cycle_error: $handle_cycle_error:literal, no_force: $no_force:literal, no_hash: $no_hash:literal, returns_error_guaranteed: $returns_error_guaranteed:literal, diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index 22f8ac9837f6d..07565254969c8 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -9,48 +9,29 @@ use rustc_errors::{Applicability, Diag, MultiSpan, pluralize, struct_span_code_e use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::bug; -use rustc_middle::queries::{QueryVTables, TaggedQueryKey}; +use rustc_middle::queries::TaggedQueryKey; use rustc_middle::query::Cycle; -use rustc_middle::query::erase::erase_val; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{ErrorGuaranteed, Span}; use crate::job::create_cycle_error; -pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) { - vtables.fn_sig.handle_cycle_error_fn = |tcx, key, _, err| { - let guar = err.delay_as_bug(); - erase_val(fn_sig(tcx, key, guar)) - }; - - vtables.check_representability.handle_cycle_error_fn = - |tcx, _, cycle, _err| check_representability(tcx, cycle); - - vtables.check_representability_adt_ty.handle_cycle_error_fn = - |tcx, _, cycle, _err| check_representability(tcx, cycle); - - vtables.variances_of.handle_cycle_error_fn = |tcx, key, _, err| { - let _guar = err.delay_as_bug(); - erase_val(variances_of(tcx, key)) - }; - - vtables.layout_of.handle_cycle_error_fn = |tcx, _, cycle, err| { - let _guar = err.delay_as_bug(); - erase_val(Err(layout_of(tcx, cycle))) - } -} - +// Default cycle handler used for all queries that don't use the `handle_cycle_error` query +// modifier. pub(crate) fn default(err: Diag<'_>) -> ! { let guar = err.emit(); guar.raise_fatal() } -fn fn_sig<'tcx>( +pub(crate) fn fn_sig<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, - guar: ErrorGuaranteed, + _: Cycle<'tcx>, + err: Diag<'_>, ) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + let guar = err.delay_as_bug(); + let err = Ty::new_error(tcx, guar); let arity = if let Some(node) = tcx.hir_get_if_local(def_id) @@ -71,7 +52,25 @@ fn fn_sig<'tcx>( ))) } -fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> ! { +pub(crate) fn check_representability<'tcx>( + tcx: TyCtxt<'tcx>, + _key: LocalDefId, + cycle: Cycle<'tcx>, + _err: Diag<'_>, +) { + check_representability_inner(tcx, cycle); +} + +pub(crate) fn check_representability_adt_ty<'tcx>( + tcx: TyCtxt<'tcx>, + _key: Ty<'tcx>, + cycle: Cycle<'tcx>, + _err: Diag<'_>, +) { + check_representability_inner(tcx, cycle); +} + +fn check_representability_inner<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> ! { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for frame in &cycle.frames { @@ -102,7 +101,13 @@ fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> ! { guar.raise_fatal() } -fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::Variance] { +pub(crate) fn variances_of<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + _cycle: Cycle<'tcx>, + err: Diag<'_>, +) -> &'tcx [ty::Variance] { + let _guar = err.delay_as_bug(); let n = tcx.generics_of(def_id).own_params.len(); tcx.arena.alloc_from_iter(iter::repeat_n(ty::Bivariant, n)) } @@ -126,7 +131,13 @@ fn search_for_cycle_permutation( otherwise() } -fn layout_of<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> &'tcx ty::layout::LayoutError<'tcx> { +pub(crate) fn layout_of<'tcx>( + tcx: TyCtxt<'tcx>, + _key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, + cycle: Cycle<'tcx>, + err: Diag<'_>, +) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { + let _guar = err.delay_as_bug(); let diag = search_for_cycle_permutation( &cycle.frames, |frames| { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index de03b48394b10..27bfe1451f64f 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -48,11 +48,9 @@ pub fn query_system<'tcx>( on_disk_cache: Option, incremental: bool, ) -> QuerySystem<'tcx> { - let mut query_vtables = query_impl::make_query_vtables(incremental); - handle_cycle_error::specialize_query_vtables(&mut query_vtables); QuerySystem { arenas: Default::default(), - query_vtables, + query_vtables: query_impl::make_query_vtables(incremental), side_effects: Default::default(), on_disk_cache, local_providers, diff --git a/compiler/rustc_query_impl/src/query_impl.rs b/compiler/rustc_query_impl/src/query_impl.rs index c1e7f3ef3cdb6..101bf2c4e80f7 100644 --- a/compiler/rustc_query_impl/src/query_impl.rs +++ b/compiler/rustc_query_impl/src/query_impl.rs @@ -22,6 +22,7 @@ macro_rules! define_queries { desc: $desc:expr, eval_always: $eval_always:literal, feedable: $feedable:literal, + handle_cycle_error: $handle_cycle_error:literal, no_force: $no_force:literal, no_hash: $no_hash:literal, returns_error_guaranteed: $returns_error_guaranteed:literal, @@ -144,7 +145,6 @@ macro_rules! define_queries { -> QueryVTable<'tcx, rustc_middle::queries::$name::Cache<'tcx>> { use rustc_middle::queries::$name::Value; - QueryVTable { name: stringify!($name), eval_always: $eval_always, @@ -177,9 +177,13 @@ macro_rules! define_queries { #[cfg(not($cache_on_disk))] try_load_from_disk_fn: |_tcx, _key, _prev_index, _index| None, - // The default just emits `err` and then aborts. - // `handle_cycle_error::specialize_query_vtables` overwrites this default - // for certain queries. + #[cfg($handle_cycle_error)] + handle_cycle_error_fn: |tcx, key, cycle, err| { + use rustc_middle::query::erase::erase_val; + + erase_val($crate::handle_cycle_error::$name(tcx, key, cycle, err)) + }, + #[cfg(not($handle_cycle_error))] handle_cycle_error_fn: |_tcx, _key, _cycle, err| { $crate::handle_cycle_error::default(err) },