From c7aa46822b74e69670853b9380e2519d7727bc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 14 Jun 2023 02:52:07 +0200 Subject: [PATCH 1/2] Don't use queries when printing the query stack --- compiler/rustc_interface/src/util.rs | 2 +- compiler/rustc_macros/src/query.rs | 12 +- compiler/rustc_middle/src/query/mod.rs | 158 +++++++-------- compiler/rustc_middle/src/query/print.rs | 181 ++++++++++++++++++ compiler/rustc_middle/src/ty/context.rs | 25 +++ compiler/rustc_middle/src/ty/print/mod.rs | 12 +- compiler/rustc_query_impl/src/plumbing.rs | 37 +++- compiler/rustc_query_system/src/query/job.rs | 2 +- compiler/rustc_query_system/src/query/mod.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 7 +- 10 files changed, 329 insertions(+), 109 deletions(-) create mode 100644 compiler/rustc_middle/src/query/print.rs diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index ad35dbbc8f965..eb843b33c5380 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -193,7 +193,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( // locals to it. The new thread runs the deadlock handler. let query_map = tls::with(|tcx| { QueryCtxt::new(tcx) - .try_collect_active_jobs() + .try_collect_active_jobs(true) .expect("active jobs shouldn't be locked in deadlock handler") }); let registry = rayon_core::Registry::current(); diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index d0d41c614d608..a194d867ee7a8 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -273,11 +273,15 @@ fn add_query_desc_cached_impl( let desc = quote! { #[allow(unused_variables)] - pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String { - let (#tcx, #key) = (tcx, key); - ::rustc_middle::ty::print::with_no_trimmed_paths!( + pub fn #name<'tcx>( + tcx: TyCtxt<'tcx>, + key: crate::query::queries::#name::Key<'tcx>, + use_queries: bool + ) -> String { + ::rustc_middle::query::print::run(tcx, use_queries, |ctx| { + let (#tcx, #key) = (ctx, ctx.arg(key)); format!(#desc) - ) + }) } }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 94ae0dcb51728..c7641df6c4f98 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,10 +47,7 @@ use crate::ty::layout::ValidityRequirement; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::GeneratorDiagnosticData; use crate::ty::TyCtxtFeed; -use crate::ty::{ - self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, - UnusedGenericParams, -}; +use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_arena::TypedArena; use rustc_ast as ast; @@ -91,6 +88,7 @@ use std::sync::Arc; pub mod erase; mod keys; +pub mod print; pub use keys::{AsLocalKey, Key, LocalCrate}; pub mod on_disk_cache; #[macro_use] @@ -229,12 +227,14 @@ rustc_queries! { desc { |tcx| "{action} `{path}`", action = { - use rustc_hir::def::DefKind; - match tcx.def_kind(key) { - DefKind::TyAlias { .. } => "expanding type alias", - DefKind::TraitAlias => "expanding trait alias", - _ => "computing type of", - } + key.map_with_tcx(|tcx, key| { + use rustc_hir::def::DefKind; + match tcx.def_kind(key) { + DefKind::TyAlias { .. } => "expanding type alias", + DefKind::TraitAlias => "expanding trait alias", + _ => "computing type of", + } + }) }, path = tcx.def_path_str(key), } @@ -324,10 +324,7 @@ rustc_queries! { query opaque_types_defined_by( key: LocalDefId ) -> &'tcx [LocalDefId] { - desc { - |tcx| "computing the opaque types defined by `{}`", - tcx.def_path_str(key.to_def_id()) - } + desc { |tcx| "computing the opaque types defined by `{}`", tcx.def_path_str(key) } } /// Returns the list of bounds that can be used for @@ -560,7 +557,7 @@ rustc_queries! { /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` /// MIR pass (assuming the -Cinstrument-coverage option is enabled). query coverageinfo(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageInfo { - desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) } + desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.map(|key| key.def_id())) } arena_cache } @@ -672,15 +669,15 @@ rustc_queries! { /// This is used to avoid cycles in resolving types like `T::Item`. query super_predicates_that_define_assoc_item(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", - tcx.def_path_str(key.0), - key.1 + tcx.def_path_str(key.i_0()), + key.i_1() } } /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. query type_param_predicates(key: (LocalDefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) } + desc { |tcx| "computing the bounds for type parameter `{}`", key.map_with_tcx(|tcx, key| tcx.hir().ty_param_name(key.1)) } } query trait_def(key: DefId) -> &'tcx ty::TraitDef { @@ -825,7 +822,10 @@ rustc_queries! { /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding /// associated item. query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { - desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) } + desc { |tcx| + "creates the associated item corresponding to the opaque type `{}`", + tcx.def_path_str(opaque_ty_def_id.map(|opaque_ty_def_id| opaque_ty_def_id.to_def_id())) + } cache_on_disk_if { true } } @@ -896,7 +896,7 @@ rustc_queries! { /// Performs lint checking for the module. query lint_mod(key: LocalModDefId) -> () { - desc { |tcx| "linting {}", describe_as_module(key, tcx) } + desc { "linting {}", key.describe_as_module() } } query check_unused_traits(_: ()) -> () { @@ -905,34 +905,34 @@ rustc_queries! { /// Checks the attributes in the module. query check_mod_attrs(key: LocalModDefId) -> () { - desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } + desc { "checking attributes in {}", key.describe_as_module() } } /// Checks for uses of unstable APIs in the module. query check_mod_unstable_api_usage(key: LocalModDefId) -> () { - desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } + desc { "checking for unstable API usage in {}", key.describe_as_module() } } /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`). query check_mod_const_bodies(key: LocalModDefId) -> () { - desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) } + desc { "checking consts in {}", key.describe_as_module() } } /// Checks the loops in the module. query check_mod_loops(key: LocalModDefId) -> () { - desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } + desc { "checking loops in {}", key.describe_as_module() } } query check_mod_naked_functions(key: LocalModDefId) -> () { - desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) } + desc { "checking naked functions in {}", key.describe_as_module() } } query check_mod_item_types(key: LocalModDefId) -> () { - desc { |tcx| "checking item types in {}", describe_as_module(key, tcx) } + desc { "checking item types in {}", key.describe_as_module() } } query check_mod_privacy(key: LocalModDefId) -> () { - desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } + desc { "checking privacy in {}", key.describe_as_module() } } query check_liveness(key: LocalDefId) { @@ -952,19 +952,19 @@ rustc_queries! { } query check_mod_deathness(key: LocalModDefId) -> () { - desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } + desc { "checking deathness of variables in {}", key.describe_as_module() } } query check_mod_impl_wf(key: LocalModDefId) -> () { - desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } + desc { "checking that impls are well-formed in {}", key.describe_as_module() } } query check_mod_type_wf(key: LocalModDefId) -> () { - desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } + desc { "checking that types are well-formed in {}", key.describe_as_module() } } query collect_mod_item_types(key: LocalModDefId) -> () { - desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) } + desc { "collecting item types in {}", key.describe_as_module() } } /// Caches `CoerceUnsized` kinds for impls on custom types. @@ -1031,8 +1031,8 @@ rustc_queries! { fatal_cycle desc { |tcx| "computing if `{}` (transitively) calls `{}`", - key.0, - tcx.def_path_str(key.1), + key.i_0(), + tcx.def_path_str(key.i_1()), } } @@ -1041,7 +1041,7 @@ rustc_queries! { fatal_cycle desc { |tcx| "computing all local function calls in `{}`", - tcx.def_path_str(key.def_id()), + tcx.def_path_str(key.map(|key| key.def_id())), } } @@ -1050,9 +1050,9 @@ rustc_queries! { /// **Do not use this** directly, use the `tcx.eval_static_initializer` wrapper. query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> EvalToAllocationRawResult<'tcx> { - desc { |tcx| + desc { "const-evaluating + checking `{}`", - key.value.display(tcx) + key.value().display() } cache_on_disk_if { true } } @@ -1065,9 +1065,9 @@ rustc_queries! { /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> EvalToConstValueResult<'tcx> { - desc { |tcx| + desc { "simplifying constant for the type system `{}`", - key.value.display(tcx) + key.value().display() } cache_on_disk_if { true } } @@ -1141,7 +1141,7 @@ rustc_queries! { /// Generates a MIR body for the shim. query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> { arena_cache - desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } + desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.map(|key| key.def_id())) } } /// The `symbol_name` query provides the symbol name for calling a @@ -1267,18 +1267,18 @@ rustc_queries! { query vtable_entries(key: ty::PolyTraitRef<'tcx>) -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) } + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.map(|key| key.def_id())) } } query vtable_trait_upcasting_coercion_new_vptr_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option { desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable", - key.1, key.0 } + key.i_1(), key.i_0() } } query vtable_allocation(key: (Ty<'tcx>, Option>)) -> mir::interpret::AllocId { desc { |tcx| "vtable const allocation for <{} as {}>", - key.0, - key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned()) + key.i_0(), + key.map(|key| key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned())) } } @@ -1286,7 +1286,7 @@ rustc_queries! { key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.1 } + desc { |tcx| "computing candidate for `{}`", key.i_1() } } /// Return all `impl` blocks in the current crate. @@ -1333,27 +1333,27 @@ rustc_queries! { /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Copy`", env.value } + desc { "computing whether `{}` is `Copy`", env.value() } } /// Query backing `Ty::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Sized`", env.value } + desc { "computing whether `{}` is `Sized`", env.value() } } /// Query backing `Ty::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is freeze", env.value } + desc { "computing whether `{}` is freeze", env.value() } } /// Query backing `Ty::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Unpin`", env.value } + desc { "computing whether `{}` is `Unpin`", env.value() } } /// Query backing `Ty::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` needs drop", env.value } + desc { "computing whether `{}` needs drop", env.value() } } /// Query backing `Ty::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` has a significant drop", env.value } + desc { "computing whether `{}` has a significant drop", env.value() } } /// Query backing `Ty::is_structural_eq_shallow`. @@ -1392,7 +1392,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit - desc { "computing layout of `{}`", key.value } + desc { "computing layout of `{}`", key.value() } } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. @@ -1402,7 +1402,7 @@ rustc_queries! { query fn_abi_of_fn_ptr( key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}` function pointers", key.value.0 } + desc { "computing call ABI of `{}` function pointers", key.value().i_0() } } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1413,7 +1413,7 @@ rustc_queries! { query fn_abi_of_instance( key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}`", key.value.0 } + desc { "computing call ABI of `{}`", key.value().i_0() } } query dylib_dependency_formats(_: CrateNum) @@ -1679,7 +1679,7 @@ rustc_queries! { /// For `T` in `struct Foo<'a, T: 'a>`, this would instead be `'a`. /// This query will panic if passed something that is not a type parameter. query object_lifetime_default(key: DefId) -> ObjectLifetimeDefault { - desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) } + desc { |tcx| "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) } separate_provide_extern } query late_bound_vars_map(_: hir::OwnerId) @@ -1899,7 +1899,7 @@ rustc_queries! { cache_on_disk_if { key.def_id().is_local() } desc { |tcx| "determining which generic parameters are unused by `{}`", - tcx.def_path_str(key.def_id()) + tcx.def_path_str(key.map(|key| key.def_id())) } separate_provide_extern } @@ -1925,7 +1925,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution, > { - desc { "normalizing `{}`", goal.value.value } + desc { "normalizing `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: invoke `normalize` instead. @@ -1935,7 +1935,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution, > { - desc { "normalizing `{}`", goal.value.value } + desc { "normalizing `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: invoke `normalize` instead. @@ -1945,14 +1945,14 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution, > { - desc { "normalizing `{}`", goal.value.value } + desc { "normalizing `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. query try_normalize_generic_arg_after_erasing_regions( goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> ) -> Result, NoSolution> { - desc { "normalizing `{}`", goal.value } + desc { "normalizing `{}`", goal.value() } } query implied_outlives_bounds( @@ -1961,7 +1961,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, NoSolution, > { - desc { "computing implied outlives bounds for `{}`", goal.value.value } + desc { "computing implied outlives bounds for `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: @@ -1972,7 +1972,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution, > { - desc { "computing dropck types for `{}`", goal.value.value } + desc { "computing dropck types for `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or @@ -1980,7 +1980,7 @@ rustc_queries! { query evaluate_obligation( goal: CanonicalPredicateGoal<'tcx> ) -> Result { - desc { "evaluating trait selection obligation `{}`", goal.value.value } + desc { "evaluating trait selection obligation `{}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: part of the `Eq` type-op @@ -1990,7 +1990,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value } + desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: part of the `Eq` type-op @@ -2000,7 +2000,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_eq` `{:?}`", goal.value.value } + desc { "evaluating `type_op_eq` `{:?}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: part of the `Subtype` type-op @@ -2010,7 +2010,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value } + desc { "evaluating `type_op_subtype` `{:?}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: part of the `ProvePredicate` type-op @@ -2020,7 +2020,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.value.value } + desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.map(|goal| goal.value.value) } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2030,7 +2030,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, NoSolution, > { - desc { "normalizing `{}`", goal.value.value.value } + desc { "normalizing `{}`", goal.map(|goal| goal.value.value.value) } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2040,7 +2040,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.value.value.value } + desc { "normalizing `{:?}`", goal.map(|goal| goal.value.value.value) } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2050,7 +2050,7 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.value.value.value } + desc { "normalizing `{:?}`", goal.map(|goal| goal.value.value.value) } } /// Do not call this query directly: part of the `Normalize` type-op @@ -2060,28 +2060,28 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, NoSolution, > { - desc { "normalizing `{:?}`", goal.value.value.value } + desc { "normalizing `{:?}`", goal.map(|goal| goal.value.value.value) } } query subst_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { desc { |tcx| "checking impossible substituted predicates: `{}`", - tcx.def_path_str(key.0) + tcx.def_path_str(key.i_0()) } } query is_impossible_associated_item(key: (DefId, DefId)) -> bool { desc { |tcx| "checking if `{}` is impossible to reference within `{}`", - tcx.def_path_str(key.1), - tcx.def_path_str(key.0), + tcx.def_path_str(key.i_1()), + tcx.def_path_str(key.i_0()), } } query method_autoderef_steps( goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { - desc { "computing autoderef types for `{}`", goal.value.value } + desc { "computing autoderef types for `{}`", goal.map(|goal| goal.value.value) } } query supported_target_features(_: CrateNum) -> &'tcx FxHashMap> { @@ -2095,7 +2095,7 @@ rustc_queries! { desc { "looking up enabled feature gates" } } - query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { + query crate_for_resolver(_: ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { feedable no_hash desc { "the ast before macro expansion and name resolution" } @@ -2113,7 +2113,7 @@ rustc_queries! { query resolve_instance( key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result>, ErrorGuaranteed> { - desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } + desc { "resolving instance `{}`", key.map(|key| ty::Instance::new(key.value.0, key.value.1)) } } query reveal_opaque_types_in_bounds(key: &'tcx ty::List>) -> &'tcx ty::List> { @@ -2138,7 +2138,7 @@ rustc_queries! { arena_cache eval_always no_hash - desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } + desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.i_0(), key.i_1() } } /// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, @@ -2156,13 +2156,13 @@ rustc_queries! { } query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result> { - desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } + desc { "checking validity requirement for `{}`: {}", key.i_1().value(), key.i_0() } } query compare_impl_const( key: (LocalDefId, DefId) ) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) } + desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.i_0()) } } query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { diff --git a/compiler/rustc_middle/src/query/print.rs b/compiler/rustc_middle/src/query/print.rs new file mode 100644 index 0000000000000..81b4179dd02e8 --- /dev/null +++ b/compiler/rustc_middle/src/query/print.rs @@ -0,0 +1,181 @@ +use crate::mir::interpret::GlobalId; +use crate::query::IntoQueryParam; +use crate::query::TyCtxt; +use crate::ty; +use rustc_hir::def_id::CrateNum; +use rustc_hir::def_id::DefId; +use rustc_span::Symbol; +use std::fmt; +use std::fmt::Debug; +use std::fmt::Display; + +/// This is used to print query keys without giving them access to `TyCtxt`. +/// This enables more reliable printing when printing the query stack on panics. +#[derive(Copy, Clone)] +pub struct PrintContext<'tcx> { + tcx: TyCtxt<'tcx>, + use_queries: bool, +} + +impl<'tcx> PrintContext<'tcx> { + pub fn arg(&self, arg: T) -> PrintArg<'tcx, T> { + PrintArg { arg: Some(arg), ctx: *self } + } + + pub fn def_path_str(&self, def_id: PrintArg<'tcx, impl IntoQueryParam>) -> String { + def_id.print(|arg| { + let def_id = arg.into_query_param(); + if self.use_queries { + self.tcx.def_path_str(def_id) + } else { + self.tcx.safe_def_path_str_untracked(def_id) + } + }) + } +} + +/// This runs some code in a printing context. If `use_queries` is false this function should +/// ensure that no queries are run. +pub fn run<'tcx, R>( + tcx: TyCtxt<'tcx>, + use_queries: bool, + print: impl FnOnce(PrintContext<'tcx>) -> R, +) -> R { + let ctx = PrintContext { tcx, use_queries }; + if use_queries { ty::print::with_no_trimmed_paths!(print(ctx)) } else { print(ctx) } +} + +const INACCESSIBLE: &'static str = ""; + +/// This wraps a value that we want to print without giving access to the regular types +/// and their Display and Debug impls. `map` and `map_with_tcx` gives access to the inner +/// type, but erases the value for the no query path. +#[derive(Copy, Clone)] +pub struct PrintArg<'tcx, T> { + arg: Option, + ctx: PrintContext<'tcx>, +} + +impl<'tcx, T> PrintArg<'tcx, T> { + fn print(self, f: impl FnOnce(T) -> String) -> String { + self.arg.map(f).unwrap_or_else(|| INACCESSIBLE.to_owned()) + } + + fn fmt_map( + &self, + f: &mut fmt::Formatter<'_>, + map: impl FnOnce(&mut fmt::Formatter<'_>, &T) -> fmt::Result, + ) -> fmt::Result { + match &self.arg { + Some(arg) => map(f, arg), + _ => write!(f, "{}", INACCESSIBLE), + } + } + + fn fmt_with_queries( + &self, + f: &mut fmt::Formatter<'_>, + map: impl FnOnce(&mut fmt::Formatter<'_>, &T) -> fmt::Result, + ) -> fmt::Result { + match &self.arg { + Some(arg) if self.ctx.use_queries => map(f, arg), + _ => write!(f, "{}", INACCESSIBLE), + } + } + + pub fn ctx(&self) -> PrintContext<'tcx> { + self.ctx + } + + /// Maps the argument where `f` is known to not call queries. + fn map_unchecked(self, f: impl FnOnce(T) -> R) -> PrintArg<'tcx, R> { + PrintArg { arg: self.arg.map(f), ctx: self.ctx } + } + + pub fn map(self, f: impl FnOnce(T) -> R) -> PrintArg<'tcx, R> { + self.map_with_tcx(|_, arg| f(arg)) + } + + pub fn map_with_tcx(self, f: impl FnOnce(TyCtxt<'tcx>, T) -> R) -> PrintArg<'tcx, R> { + PrintArg { + arg: if self.ctx.use_queries { self.arg.map(|arg| f(self.ctx.tcx, arg)) } else { None }, + ctx: self.ctx, + } + } + + pub fn describe_as_module(&self) -> String + where + T: IntoQueryParam + Copy, + { + self.print(|arg| { + let def_id: DefId = arg.into_query_param(); + if def_id.is_top_level_module() { + "top-level module".to_string() + } else { + format!("module `{}`", self.ctx.def_path_str(*self)) + } + }) + } +} + +impl<'tcx, T0, T1> PrintArg<'tcx, (T0, T1)> { + pub fn i_0(self) -> PrintArg<'tcx, T0> { + self.map_unchecked(|arg| arg.0) + } + pub fn i_1(self) -> PrintArg<'tcx, T1> { + self.map_unchecked(|arg| arg.1) + } +} + +impl<'tcx, T> PrintArg<'tcx, ty::ParamEnvAnd<'tcx, T>> { + pub fn value(self) -> PrintArg<'tcx, T> { + self.map_unchecked(|arg| arg.value) + } +} + +impl<'tcx> PrintArg<'tcx, GlobalId<'tcx>> { + pub fn display(self) -> String { + self.print(|arg| { + if self.ctx.use_queries { + arg.display(self.ctx.tcx) + } else { + let instance_name = self.ctx.def_path_str(self.ctx.arg(arg.instance.def.def_id())); + if let Some(promoted) = arg.promoted { + format!("{instance_name}::{promoted:?}") + } else { + instance_name + } + } + }) + } +} + +impl Debug for PrintArg<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt_with_queries(f, |f, arg| arg.fmt(f)) + } +} + +impl Display for PrintArg<'_, T> { + default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt_with_queries(f, |f, arg| arg.fmt(f)) + } +} + +impl Display for PrintArg<'_, CrateNum> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt_map(f, |f, arg| { + if self.ctx.use_queries { + write!(f, "`{}`", arg) + } else { + write!(f, "`{}`", self.ctx.tcx.safe_crate_str_untracked(*arg)) + } + }) + } +} + +impl Display for PrintArg<'_, Symbol> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.fmt_map(f, |f, arg| fmt::Display::fmt(arg, f)) + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index be839e03cff69..559f209ef37e1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -888,6 +888,31 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Prints a CrateNum without using queries. + pub fn safe_crate_str_untracked(self, krate: CrateNum) -> String { + if krate == LOCAL_CRATE { + "crate".to_owned() + } else { + let cstore = &*self.cstore_untracked(); + cstore.crate_name(krate).as_str().to_owned() + } + } + + /// Prints a DefId without using queries. + pub fn safe_def_path_str_untracked(self, def_id: DefId) -> String { + if def_id.is_local() { + let format = self.def_path(def_id).to_string_no_crate_verbose(); + // Strip `::` from the formatted def path if present + format.strip_prefix("::").map(|stripped| stripped.to_owned()).unwrap_or(format) + } else { + format!( + "{}{}", + self.safe_crate_str_untracked(def_id.krate), + self.def_path(def_id).to_string_no_crate_verbose() + ) + } + } + pub fn def_path_debug_str(self, def_id: DefId) -> String { // We are explicitly not going through queries here in order to get // crate name and stable crate id since this code is called from debug!() diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 05871d0bc39d1..15c58b516125a 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -3,7 +3,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; // `pretty` is a separate module only for organization. @@ -327,13 +327,3 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { cx.print_const(*self) } } - -// This is only used by query descriptions -pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { - let def_id = def_id.into(); - if def_id.is_top_level_module() { - "top-level module".to_string() - } else { - format!("module `{}`", tcx.def_path_str(def_id)) - } -} diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index def6ac280b804..a71e8e54c5b90 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -78,11 +78,11 @@ impl QueryContext for QueryCtxt<'_> { tls::with_related_context(self.tcx, |icx| icx.query) } - fn try_collect_active_jobs(self) -> Option> { + fn try_collect_active_jobs(self, can_call_queries: bool) -> Option> { let mut jobs = QueryMap::default(); for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() { - collect(self.tcx, &mut jobs); + collect(self.tcx, &mut jobs, can_call_queries); } Some(jobs) @@ -153,7 +153,7 @@ impl QueryContext for QueryCtxt<'_> { fn depth_limit_error(self, job: QueryJobId) { let mut span = None; let mut layout_of_depth = None; - if let Some(map) = self.try_collect_active_jobs() { + if let Some(map) = self.try_collect_active_jobs(true) { if let Some((info, depth)) = job.try_find_layout_root(map) { span = Some(info.job.span); layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth }); @@ -296,18 +296,25 @@ pub(crate) fn create_query_frame< K: Copy + Key + for<'a> HashStable>, >( tcx: TyCtxt<'tcx>, - do_describe: fn(TyCtxt<'tcx>, K) -> String, + do_describe: fn(TyCtxt<'tcx>, K, bool) -> String, key: K, kind: DepKind, name: &'static str, + can_call_queries: bool, ) -> QueryStackFrame { + if !can_call_queries { + // Return a minimal query frame if we can't call queries + let description = do_describe(tcx, key, false); + return QueryStackFrame::new(description, None, None, None, kind, None, || Hash64::ZERO); + } + // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!( // Disable visible paths printing for performance reasons. // Showing visible path instead of any path is not that important in production. ty::print::with_no_visible_paths!( // Force filename-line mode to avoid invoking `type_of` query. - ty::print::with_forced_impl_filename_line!(do_describe(tcx, key)) + ty::print::with_forced_impl_filename_line!(do_describe(tcx, key, true)) ) ); let description = @@ -650,16 +657,28 @@ macro_rules! define_queries { } } - pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap) { - let make_query = |tcx, key| { + pub fn try_collect_active_jobs<'tcx>( + tcx: TyCtxt<'tcx>, + qmap: &mut QueryMap, + can_call_queries: bool, + ) { + let make_query = |tcx, key, can_call_queries| { let kind = rustc_middle::dep_graph::DepKind::$name; let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) + $crate::plumbing::create_query_frame( + tcx, + rustc_middle::query::descs::$name, + key, + kind, + name, + can_call_queries, + ) }; tcx.query_system.states.$name.try_collect_active_jobs( tcx, make_query, qmap, + can_call_queries, ).unwrap(); } @@ -710,7 +729,7 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap)] = + const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap, can_call_queries: bool)] = &[$(query_impl::$name::try_collect_active_jobs),*]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 1b12489244120..936ef6f816b27 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -628,7 +628,7 @@ pub fn print_query_stack( // state if it was responsible for triggering the panic. let mut count_printed = 0; let mut count_total = 0; - let query_map = qcx.try_collect_active_jobs(); + let query_map = qcx.try_collect_active_jobs(false); if let Some(ref mut file) = file { let _ = writeln!(file, "\n\nquery stack during panic:"); diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index f7619d75be768..e3e182925ca38 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -106,7 +106,7 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn try_collect_active_jobs(self) -> Option>; + fn try_collect_active_jobs(self, can_call_queries: bool) -> Option>; /// Load side effects associated to the node in the previous session. fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 4adb4eb7475be..e2c12fd399756 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -66,8 +66,9 @@ where pub fn try_collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, + make_query: fn(Qcx, K, bool) -> QueryStackFrame, jobs: &mut QueryMap, + can_call_queries: bool, ) -> Option<()> { let mut active = Vec::new(); @@ -100,7 +101,7 @@ where // Call `make_query` while we're not holding a `self.active` lock as `make_query` may call // queries leading to a deadlock. for (key, job) in active { - let query = make_query(qcx, key); + let query = make_query(qcx, key, can_call_queries); jobs.insert(job.id, QueryJobInfo { query, job }); } @@ -267,7 +268,7 @@ where Qcx: QueryContext, { let error = try_execute.find_cycle_in_stack( - qcx.try_collect_active_jobs().unwrap(), + qcx.try_collect_active_jobs(true).unwrap(), &qcx.current_query_job(), span, ); From bb619afaa283f8780979e1ff3139fedb70d9f2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 14 Jun 2023 04:31:21 +0200 Subject: [PATCH 2/2] Update tests --- .../ui/const-generics/generic_const_exprs/issue-80742.stderr | 2 +- tests/ui/higher-ranked/trait-bounds/future.classic.stderr | 4 ++-- tests/ui/impl-trait/issues/issue-86800.stderr | 2 +- tests/ui/layout/valid_range_oob.stderr | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index 79ed82e02e0d6..2751794c53382 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -3,7 +3,7 @@ error: internal compiler error: compiler/rustc_const_eval/src/interpret/step.rs: Box query stack during panic: -#0 [eval_to_allocation_raw] const-evaluating + checking `::{constant#0}` +#0 [eval_to_allocation_raw] const-evaluating + checking `{impl#0}::{constant#0}` #1 [eval_to_valtree] evaluating type-level constant end of query stack error: aborting due to previous error diff --git a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr index 33c0f7173a1d1..1396c702aac28 100644 --- a/tests/ui/higher-ranked/trait-bounds/future.classic.stderr +++ b/tests/ui/higher-ranked/trait-bounds/future.classic.stderr @@ -1,6 +1,6 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> [async fn body@$DIR/future.rs:32:35: 34:2]: core::future::future::Future` -#1 [codegen_select_candidate] computing candidate for `` +#0 [evaluate_obligation] evaluating trait selection obligation `` +#1 [codegen_select_candidate] computing candidate for `` end of query stack diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index facab390d1524..c07957e6fa3f1 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -7,6 +7,6 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future `TransactionFuture::{opaque#0}` #1 [check_mod_item_types] checking item types in top-level module end of query stack diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr index d56804a35a7f4..9b18e3723ace0 100644 --- a/tests/ui/layout/valid_range_oob.stderr +++ b/tests/ui/layout/valid_range_oob.stderr @@ -2,6 +2,6 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [layout_of] computing layout of `Foo` +#0 [layout_of] computing layout of `` #1 [eval_to_allocation_raw] const-evaluating + checking `FOO` end of query stack