diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 0e2b16d72eb15..bc6f856e86836 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -289,7 +289,7 @@ fn add_query_desc_cached_impl( cached.extend(quote! { #[allow(unused_variables, unused_braces, rustc::pass_by_value)] #[inline] - pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool { + pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::queries::#name::Key<'tcx>) -> bool { #ra_hint #expr } @@ -301,7 +301,7 @@ 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 { + pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::queries::#name::Key<'tcx>) -> String { let (#tcx, #key) = (tcx, key); format!(#desc) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7bd3f7db55f99..b1f3bafd92fb9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -11,7 +11,8 @@ use rustc_middle::bug; use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; -use rustc_middle::query::{ExternProviders, LocalCrate}; +use rustc_middle::queries::ExternProviders; +use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; @@ -134,8 +135,8 @@ macro_rules! provide_one { ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => { fn $name<'tcx>( $tcx: TyCtxt<'tcx>, - def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>, - ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> { + def_id_arg: rustc_middle::queries::$name::Key<'tcx>, + ) -> rustc_middle::queries::$name::ProvidedValue<'tcx> { let _prof_timer = $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name))); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5682c21e43533..bb94b4c927ae0 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -86,6 +86,8 @@ mod values; #[macro_use] pub mod query; #[macro_use] +pub mod queries; +#[macro_use] pub mod dep_graph; // Allows macros to refer to this crate as `::rustc_middle` diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs new file mode 100644 index 0000000000000..ca8e5e90318da --- /dev/null +++ b/compiler/rustc_middle/src/queries.rs @@ -0,0 +1,2775 @@ +//! +//! # The rustc Query System: Query Definitions and Modifiers +//! +//! The core processes in rustc are shipped as queries. Each query is a demand-driven function from some key to a value. +//! The execution result of the function is cached and directly read during the next request, thereby improving compilation efficiency. +//! Some results are saved locally and directly read during the next compilation, which are core of incremental compilation. +//! +//! ## How to Read This Module +//! +//! Each `query` block in this file defines a single query, specifying its key and value types, along with various modifiers. +//! These query definitions are processed by the [`rustc_macros`], which expands them into the necessary boilerplate code +//! for the query system—including the [`Providers`] struct (a function table for all query implementations, where each field is +//! a function pointer to the actual provider), caching, and dependency graph integration. +//! **Note:** The `Providers` struct is not a Rust trait, but a struct generated by the `rustc_macros` to hold all provider functions. +//! The `rustc_macros` also supports a set of **query modifiers** (see below) that control the behavior of each query. +//! +//! The actual provider functions are implemented in various modules and registered into the `Providers` struct +//! during compiler initialization (see [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]). +//! +//! [`rustc_macros`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/index.html +//! [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]: ../../rustc_interface/passes/static.DEFAULT_QUERY_PROVIDERS.html +//! +//! ## Query Modifiers +//! +//! Query modifiers are special flags that alter the behavior of a query. They are parsed and processed by the `rustc_macros` +//! The main modifiers are: +//! +//! - `desc { ... }`: Sets the human-readable description for diagnostics and profiling. Required for every query. +//! - `arena_cache`: Use an arena for in-memory caching of the query result. +//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to true. +//! - `cycle_fatal`: If a dependency cycle is detected, abort compilation with a fatal error. +//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. +//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. +//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. +//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). +//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. +//! - `depth_limit`: Impose a recursion depth limit on the query to prevent stack overflows. +//! - `separate_provide_extern`: Use separate provider functions for local and external crates. +//! - `feedable`: Allow the query result to be set from another query ("fed" externally). +//! - `return_result_from_ensure_ok`: When called via `tcx.ensure_ok()`, return `Result<(), ErrorGuaranteed>` instead of `()`. +//! If the query needs to be executed and returns an error, the error is returned to the caller. +//! Only valid for queries returning `Result<_, ErrorGuaranteed>`. +//! +//! For the up-to-date list, see the `QueryModifiers` struct in +//! [`rustc_macros/src/query.rs`](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_macros/src/query.rs) +//! and for more details in incremental compilation, see the +//! [Query modifiers in incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#query-modifiers) section of the rustc-dev-guide. +//! +//! ## Query Expansion and Code Generation +//! +//! The [`rustc_macros::rustc_queries`] macro expands each query definition into: +//! - A method on [`TyCtxt`] (and [`crate::query::TyCtxtAt`]) for invoking the query. +//! - Provider traits and structs for supplying the query's value. +//! - Caching and dependency graph integration. +//! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. +//! +//! [`rustc_macros::rustc_queries`]: ../../rustc_macros/macro.rustc_queries.html +//! +//! The macro-based approach allows the query system to be highly flexible and maintainable, while minimizing boilerplate. +//! +//! For more details, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). + +#![allow(unused_parens)] + +use std::ffi::OsStr; +use std::mem; +use std::path::PathBuf; +use std::sync::Arc; + +use rustc_abi::Align; +use rustc_arena::TypedArena; +use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::tokenstream::TokenStream; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::svh::Svh; +use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::ErrorGuaranteed; +use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem}; +use rustc_hir::def::{DefKind, DocLinkResMap}; +use rustc_hir::def_id::{ + CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, +}; +use rustc_hir::lang_items::{LangItem, LanguageItems}; +use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; +use rustc_index::IndexVec; +use rustc_lint_defs::LintId; +use rustc_macros::rustc_queries; +use rustc_session::Limits; +use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::cstore::{ + CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, +}; +use rustc_session::lint::LintExpectationId; +use rustc_span::def_id::LOCAL_CRATE; +use rustc_span::source_map::Spanned; +use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; +use rustc_target::spec::PanicStrategy; +use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; + +use crate::infer::canonical::{self, Canonical}; +use crate::lint::LintExpectation; +use crate::metadata::ModChild; +use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; +use crate::middle::debugger_visualizer::DebuggerVisualizerFile; +use crate::middle::deduced_param_attrs::DeducedParamAttrs; +use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use crate::middle::lib_features::LibFeatures; +use crate::middle::privacy::EffectiveVisibilities; +use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; +use crate::middle::stability::DeprecationEntry; +use crate::mir::interpret::{ + EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, + EvalToValTreeResult, GlobalId, LitToConstInput, +}; +use crate::mir::mono::{ + CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, +}; +use crate::query::describe_as_module; +use crate::query::plumbing::CyclePlaceholder; +use crate::traits::query::{ + CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, + CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, + CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint, + DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult, + OutlivesBound, +}; +use crate::traits::{ + CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource, + ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph, +}; +use crate::ty::fast_reject::SimplifiedType; +use crate::ty::layout::ValidityRequirement; +use crate::ty::print::PrintTraitRefExt; +use crate::ty::util::AlwaysRequiresDrop; +use crate::ty::{ + self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty, + TyCtxt, TyCtxtFeed, +}; +use crate::{dep_graph, mir, thir}; + +// Each of these queries corresponds to a function pointer field in the +// `Providers` struct for requesting a value of that type, and a method +// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way +// which memoizes and does dep-graph tracking, wrapping around the actual +// `Providers` that the driver creates (using several `rustc_*` crates). +// +// The result type of each query must implement `Clone`, and additionally +// `ty::query::values::Value`, which produces an appropriate placeholder +// (error) value if the query resulted in a query cycle. +// Queries marked with `cycle_fatal` do not need the latter implementation, +// as they will raise an fatal error on query cycles instead. +rustc_queries! { + /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`. + /// The key is: + /// - A unique key corresponding to the invocation of a macro. + /// - Token stream which serves as an input to the macro. + /// + /// The output is the token stream generated by the proc macro. + query derive_macro_expansion(key: (LocalExpnId, &'tcx TokenStream)) -> Result<&'tcx TokenStream, ()> { + desc { "expanding a derive (proc) macro" } + cache_on_disk_if { true } + } + + /// This exists purely for testing the interactions between delayed bugs and incremental. + query trigger_delayed_bug(key: DefId) { + desc { "triggering a delayed bug for testing incremental" } + } + + /// Collects the list of all tools registered using `#![register_tool]`. + query registered_tools(_: ()) -> &'tcx ty::RegisteredTools { + arena_cache + desc { "compute registered tools for crate" } + } + + query early_lint_checks(_: ()) { + desc { "perform lints prior to AST lowering" } + } + + /// Tracked access to environment variables. + /// + /// Useful for the implementation of `std::env!`, `proc-macro`s change + /// detection and other changes in the compiler's behaviour that is easier + /// to control with an environment variable than a flag. + /// + /// NOTE: This currently does not work with dependency info in the + /// analysis, codegen and linking passes, place extra code at the top of + /// `rustc_interface::passes::write_dep_info` to make that work. + query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { + // Environment variables are global state + eval_always + desc { "get the value of an environment variable" } + } + + query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { + desc { "getting the resolver outputs" } + } + + query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc)>, &'tcx ty::ResolverGlobalCtxt) { + eval_always + no_hash + desc { "getting the resolver for lowering" } + } + + /// Return the span for a definition. + /// + /// Contrary to `def_span` below, this query returns the full absolute span of the definition. + /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside + /// of rustc_middle::hir::source_map. + query source_span(key: LocalDefId) -> Span { + // Accesses untracked data + eval_always + desc { "getting the source span" } + } + + /// Represents crate as a whole (as distinct from the top-level crate module). + /// + /// If you call `tcx.hir_crate(())` we will have to assume that any change + /// means that you need to be recompiled. This is because the `hir_crate` + /// query gives you access to all other items. To avoid this fate, do not + /// call `tcx.hir_crate(())`; instead, prefer wrappers like + /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. + query hir_crate(key: ()) -> &'tcx Crate<'tcx> { + arena_cache + eval_always + desc { "getting the crate HIR" } + } + + /// All items in the crate. + query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems { + arena_cache + eval_always + desc { "getting HIR crate items" } + } + + /// The items in a module. + /// + /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`. + /// Avoid calling this query directly. + query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { + arena_cache + desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + + /// Returns HIR ID for the given `LocalDefId`. + query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { + desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to the HIR node's parent for the HIR owner `key`. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query hir_owner_parent_q(key: hir::OwnerId) -> hir::HirId { + desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } + } + + /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { + desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to the HIR attributes inside the HIR owner `key`. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { + desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) } + feedable + } + + /// Gives access to lints emitted during ast lowering. + /// + /// This can be conveniently accessed by `tcx.hir_*` methods. + /// Avoid calling this query directly. + query opt_ast_lowering_delayed_lints(key: hir::OwnerId) -> Option<&'tcx hir::lints::DelayedLints> { + desc { |tcx| "getting AST lowering delayed lints in `{}`", tcx.def_path_str(key) } + } + + /// Returns the *default* of the const pararameter given by `DefId`. + /// + /// E.g., given `struct Ty;` this returns `3` for `N`. + query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + desc { |tcx| "computing the default for const parameter `{}`", tcx.def_path_str(param) } + cache_on_disk_if { param.is_local() } + separate_provide_extern + } + + /// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`. + /// + /// When a const item is used in a type-level expression, like in equality for an assoc const + /// projection, this allows us to retrieve the typesystem-appropriate representation of the + /// const value. + /// + /// This query will ICE if given a const that is not marked with `#[type_const]`. + query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Returns the *type* of the definition given by `DefId`. + /// + /// For type aliases (whether eager or lazy) and associated types, this returns + /// the underlying aliased type (not the corresponding [alias type]). + /// + /// For opaque types, this returns and thus reveals the hidden type! If you + /// want to detect cycle errors use `type_of_opaque` instead. + /// + /// To clarify, for type definitions, this does *not* return the "type of a type" + /// (aka *kind* or *sort*) in the type-theoretical sense! It merely returns + /// the type primarily *associated with* it. + /// + /// # Panics + /// + /// This query will panic if the given definition doesn't (and can't + /// conceptually) have an (underlying) type. + /// + /// [alias type]: rustc_middle::ty::AliasTy + query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + desc { |tcx| + "{action} `{path}`", + action = match tcx.def_kind(key) { + DefKind::TyAlias => "expanding type alias", + DefKind::TraitAlias => "expanding trait alias", + _ => "computing type of", + }, + path = tcx.def_path_str(key), + } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. + /// + /// This is a specialized instance of [`Self::type_of`] that detects query cycles. + /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. + /// This is used to improve the error message in cases where revealing the hidden type + /// for auto-trait leakage cycles. + /// + /// # Panics + /// + /// This query will panic if the given definition is not an opaque type. + query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { + desc { |tcx| + "computing type of opaque `{path}`", + path = tcx.def_path_str(key), + } + cycle_stash + } + query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + desc { |tcx| + "computing type of opaque `{path}` via HIR typeck", + path = tcx.def_path_str(key), + } + } + + /// Returns whether the type alias given by `DefId` is lazy. + /// + /// I.e., if the type alias expands / ought to expand to a [free] [alias type] + /// instead of the underlying aliased type. + /// + /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. + /// + /// # Panics + /// + /// This query *may* panic if the given definition is not a type alias. + /// + /// [free]: rustc_middle::ty::Free + /// [alias type]: rustc_middle::ty::AliasTy + query type_alias_is_lazy(key: DefId) -> bool { + desc { |tcx| + "computing whether the type alias `{path}` is lazy", + path = tcx.def_path_str(key), + } + separate_provide_extern + } + + query collect_return_position_impl_trait_in_trait_tys(key: DefId) + -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> + { + desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin + { + desc { "determine where the opaque originates from" } + separate_provide_extern + } + + query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet + { + arena_cache + desc { |tcx| + "determining what parameters of `{}` can participate in unsizing", + tcx.def_path_str(key), + } + } + + /// The root query triggering all analysis passes like typeck or borrowck. + query analysis(key: ()) { + eval_always + desc { |tcx| + "running analysis passes on crate `{}`", + tcx.crate_name(LOCAL_CRATE), + } + } + + /// This query checks the fulfillment of collected lint expectations. + /// All lint emitting queries have to be done before this is executed + /// to ensure that all expectations can be fulfilled. + /// + /// This is an extra query to enable other drivers (like rustdoc) to + /// only execute a small subset of the `analysis` query, while allowing + /// lints to be expected. In rustc, this query will be executed as part of + /// the `analysis` query and doesn't have to be called a second time. + /// + /// Tools can additionally pass in a tool filter. That will restrict the + /// expectations to only trigger for lints starting with the listed tool + /// name. This is useful for cases were not all linting code from rustc + /// was called. With the default `None` all registered lints will also + /// be checked for expectation fulfillment. + query check_expectations(key: Option) { + eval_always + desc { "checking lint expectations (RFC 2383)" } + } + + /// Returns the *generics* of the definition given by `DefId`. + query generics_of(key: DefId) -> &'tcx ty::Generics { + desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } + arena_cache + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the (elaborated) *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). + /// + /// This is almost always *the* "predicates query" that you want. + /// + /// **Tip**: You can use `#[rustc_dump_predicates]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. + query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + } + + query opaque_types_defined_by( + key: LocalDefId + ) -> &'tcx ty::List { + desc { + |tcx| "computing the opaque types defined by `{}`", + tcx.def_path_str(key.to_def_id()) + } + } + + /// A list of all bodies inside of `key`, nested bodies are always stored + /// before their parent. + query nested_bodies_within( + key: LocalDefId + ) -> &'tcx ty::List { + desc { + |tcx| "computing the coroutines defined within `{}`", + tcx.def_path_str(key.to_def_id()) + } + } + + /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). + /// + /// For associated types, these must be satisfied for an implementation + /// to be well-formed, and for opaque types, these are required to be + /// satisfied by the hidden type of the opaque. + /// + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. + /// + /// Syntactially, these are the bounds written on associated types in trait + /// definitions, or those after the `impl` keyword for an opaque: + /// + /// ```ignore (illustrative) + /// trait Trait { type X: Bound + 'lt; } + /// // ^^^^^^^^^^^ + /// fn function() -> impl Debug + Display { /*...*/ } + /// // ^^^^^^^^^^^^^^^ + /// ``` + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the explicitly user-written *bounds* that share the `Self` type of the item. + /// + /// These are a subset of the [explicit item bounds] that may explicitly be used for things + /// like closure signature deduction. + /// + /// [explicit item bounds]: Self::explicit_item_bounds + query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the (elaborated) *bounds* on the associated or opaque type given by `DefId` + /// that must be proven true at definition site (and which can be assumed at usage sites). + /// + /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. + /// + /// **Tip**: You can use `#[rustc_dump_item_bounds]` on an item to basically print + /// the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples + /// + /// ``` + /// trait Trait { type Assoc: Eq + ?Sized; } + /// ``` + /// + /// While [`Self::explicit_item_bounds`] returns `[::Assoc: Eq]` + /// here, `item_bounds` returns: + /// + /// ```text + /// [ + /// ::Assoc: Eq, + /// ::Assoc: PartialEq<::Assoc> + /// ] + /// ``` + query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } + } + + query item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } + } + + query item_non_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } + } + + query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } + } + + /// Look up all native libraries this crate depends on. + /// These are assembled from the following places: + /// - `extern` blocks (depending on their `link` attributes) + /// - the `libs` (`-l`) option + query native_libraries(_: CrateNum) -> &'tcx Vec { + arena_cache + desc { "looking up the native libraries of a linked crate" } + separate_provide_extern + } + + query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap { + arena_cache + desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) } + } + + query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> { + arena_cache + desc { "computing `#[expect]`ed lints in this crate" } + } + + query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { + arena_cache + desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" } + } + + query expn_that_defined(key: DefId) -> rustc_span::ExpnId { + desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + query is_panic_runtime(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate is_panic_runtime" } + separate_provide_extern + } + + /// Checks whether a type is representable or infinitely sized + query representability(_: LocalDefId) -> rustc_middle::ty::Representability { + desc { "checking if `{}` is representable", tcx.def_path_str(key) } + // infinitely sized types will cause a cycle + cycle_delay_bug + // 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 + anon + } + + /// An implementation detail for the `representability` query + query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability { + desc { "checking if `{}` is representable", key } + cycle_delay_bug + anon + } + + /// Set of param indexes for type params that are in the type's representation + query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet { + desc { "finding type parameters in the representation" } + arena_cache + no_hash + separate_provide_extern + } + + /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless + /// `-Zno-steal-thir` is on. + query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { + // Perf tests revealed that hashing THIR is inefficient (see #85729). + no_hash + desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) } + } + + /// Set of all the `DefId`s in this crate that have MIR associated with + /// them. This includes all the body owners, but also things like struct + /// constructors. + query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet { + arena_cache + desc { "getting a list of all mir_keys" } + } + + /// Maps DefId's that have an associated `mir::Body` to the result + /// of the MIR const-checking pass. This is the set of qualifs in + /// the final value of a `const`. + query mir_const_qualif(key: DefId) -> mir::ConstQualifs { + desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Build the MIR for a given `DefId` and prepare it for const qualification. + /// + /// See the [rustc dev guide] for more info. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html + query mir_built(key: LocalDefId) -> &'tcx Steal> { + desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } + feedable + } + + /// Try to build an abstract representation of the given constant. + query thir_abstract_const( + key: DefId + ) -> Result>>, ErrorGuaranteed> { + desc { + |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), + } + separate_provide_extern + } + + query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal> { + no_hash + desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) } + } + + query mir_for_ctfe( + key: DefId + ) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query mir_promoted(key: LocalDefId) -> ( + &'tcx Steal>, + &'tcx Steal>> + ) { + no_hash + desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } + } + + query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> { + desc { + |tcx| "finding symbols for captures of closure `{}`", + tcx.def_path_str(key) + } + } + + /// Returns names of captured upvars for closures and coroutines. + /// + /// Here are some examples: + /// - `name__field1__field2` when the upvar is captured by value. + /// - `_ref__name__field` when the upvar is captured by reference. + /// + /// For coroutines this only contains upvars that are shared by all states. + query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec { + arena_cache + desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { + arena_cache + desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that + /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck. + /// + /// However, we replace each free region in the MIR body with a unique region inference + /// variable. As we may rely on structural identity when proving goals this may cause a + /// goal to no longer hold. We store obligations for which this may happen during HIR + /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck + /// encounters an unexpected error. We expect this to result in an error when used and + /// delay a bug if it does not. + query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { + |tcx| "reproving potentially region dependent HIR typeck goals for `{}", + tcx.def_path_str(key) + } + } + + /// MIR after our optimization passes have run. This is MIR that is ready + /// for codegen. This is also the only query that can fetch non-local MIR, at present. + query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on + /// this def and any enclosing defs, up to the crate root. + /// + /// Returns `false` if `#[coverage(off)]` was found, or `true` if + /// either `#[coverage(on)]` or no coverage attribute was found. + query coverage_attr_on(key: LocalDefId) -> bool { + desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) } + feedable + } + + /// Scans through a function's MIR after MIR optimizations, to prepare the + /// information needed by codegen when `-Cinstrument-coverage` is active. + /// + /// This includes the details of where to insert `llvm.instrprof.increment` + /// intrinsics, and the expression tables to be embedded in the function's + /// coverage metadata. + /// + /// FIXME(Zalathar): This query's purpose has drifted a bit and should + /// probably be renamed, but that can wait until after the potential + /// follow-ups to #136053 have settled down. + /// + /// Returns `None` for functions that were not instrumented. + query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { + desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } + arena_cache + } + + /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own + /// `DefId`. This function returns all promoteds in the specified body. The body references + /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because + /// after inlining a body may refer to promoteds from other bodies. In that case you still + /// need to use the `DefId` of the original body. + query promoted_mir(key: DefId) -> &'tcx IndexVec> { + desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Erases regions from `ty` to yield a new type. + /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`, + /// however, which uses this query as a kind of cache. + query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { + // This query is not expected to have input -- as a result, it + // is not a good candidates for "replay" because it is essentially a + // pure function of its input (and hence the expectation is that + // no caller would be green **apart** from just these + // queries). Making it anonymous avoids hashing the result, which + // may save a bit of time. + anon + desc { "erasing regions from `{}`", ty } + } + + query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap { + arena_cache + desc { "getting wasm import module map" } + } + + /// Returns the explicitly user-written *predicates and bounds* of the trait given by `DefId`. + /// + /// Traits are unusual, because predicates on associated types are + /// converted into bounds on that type for backwards compatibility: + /// + /// ``` + /// trait X where Self::U: Copy { type U; } + /// ``` + /// + /// becomes + /// + /// ``` + /// trait X { type U: Copy; } + /// ``` + /// + /// [`Self::explicit_predicates_of`] and [`Self::explicit_item_bounds`] will + /// then take the appropriate subsets of the predicates here. + /// + /// # Panics + /// + /// This query will panic if the given definition is not a trait. + query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) } + } + + /// Returns the explicitly user-written *predicates* of the definition given by `DefId` + /// that must be proven true at usage sites (and which can be assumed at definition site). + /// + /// You should probably use [`Self::predicates_of`] unless you're looking for + /// predicates with explicit spans for diagnostics purposes. + query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { + desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the *inferred outlives-predicates* of the item given by `DefId`. + /// + /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. + /// + /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. + query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { + desc { |tcx| "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Returns the explicitly user-written *super-predicates* of the trait given by `DefId`. + /// + /// These predicates are unelaborated and consequently don't contain transitive super-predicates. + /// + /// This is a subset of the full list of predicates. We store these in a separate map + /// because we must evaluate them even during type conversion, often before the full + /// predicates are available (note that super-predicates must not be cyclic). + query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// The predicates of the trait that are implied during elaboration. + /// + /// This is a superset of the super-predicates of the trait, but a subset of the predicates + /// of the trait. For regular traits, this includes all super-predicates and their + /// associated type bounds. For trait aliases, currently, this includes all of the + /// predicates of the trait alias. + query explicit_implied_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// The Ident is the name of an associated type.The query returns only the subset + /// of supertraits that define the given associated type. This is used to avoid + /// cycles in resolving type-dependent associated item paths like `T::Item`. + query explicit_supertraits_containing_assoc_item( + key: (DefId, rustc_span::Ident) + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", + tcx.def_path_str(key.0), + key.1 + } + } + + /// Compute the conditions that need to hold for a conditionally-const item to be const. + /// That is, compute the set of `[const]` where clauses for a given item. + /// + /// This can be thought of as the `[const]` equivalent of `predicates_of`. These are the + /// predicates that need to be proven at usage sites, and can be assumed at definition. + /// + /// This query also computes the `[const]` where clauses for associated types, which are + /// not "const", but which have item bounds which may be `[const]`. These must hold for + /// the `[const]` item bound to hold. + query const_conditions( + key: DefId + ) -> ty::ConstConditions<'tcx> { + desc { |tcx| "computing the conditions for `{}` to be considered const", + tcx.def_path_str(key) + } + separate_provide_extern + } + + /// Compute the const bounds that are implied for a conditionally-const item. + /// + /// This can be though of as the `[const]` equivalent of `explicit_item_bounds`. These + /// are the predicates that need to proven at definition sites, and can be assumed at + /// usage sites. + query explicit_implied_const_bounds( + key: DefId + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { + desc { |tcx| "computing the implied `[const]` bounds for `{}`", + tcx.def_path_str(key) + } + separate_provide_extern + } + + /// 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::Ident) + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) } + } + + query trait_def(key: DefId) -> &'tcx ty::TraitDef { + desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } + arena_cache + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_def(key: DefId) -> ty::AdtDef<'tcx> { + desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_destructor(key: DefId) -> Option { + desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_async_destructor(key: DefId) -> Option { + desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query adt_sizedness_constraint( + key: (DefId, SizedTraitKind) + ) -> Option>> { + desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) } + } + + query adt_dtorck_constraint( + key: DefId + ) -> &'tcx DropckConstraint<'tcx> { + desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } + } + + /// Returns the constness of the function-like[^1] definition given by `DefId`. + /// + /// Tuple struct/variant constructors are *always* const, foreign functions are + /// *never* const. The rest is const iff marked with keyword `const` (or rather + /// its parent in the case of associated functions). + /// + ///
+ /// + /// **Do not call this query** directly. It is only meant to cache the base data for the + /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. + /// + /// Also note that neither of them takes into account feature gates, stability and + /// const predicates/conditions! + /// + ///
+ /// + /// # Panics + /// + /// This query will panic if the given definition is not function-like[^1]. + /// + /// [^1]: Tuple struct/variant constructors, closures and free, associated and foreign functions. + query constness(key: DefId) -> hir::Constness { + desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } + separate_provide_extern + feedable + } + + query asyncness(key: DefId) -> ty::Asyncness { + desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + /// Returns `true` if calls to the function may be promoted. + /// + /// This is either because the function is e.g., a tuple-struct or tuple-variant + /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should + /// be removed in the future in favour of some form of check which figures out whether the + /// function does not inspect the bits of any of its arguments (so is essentially just a + /// constructor function). + query is_promotable_const_fn(key: DefId) -> bool { + desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } + } + + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { + desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. + query coroutine_kind(def_id: DefId) -> Option { + desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + query coroutine_for_closure(def_id: DefId) -> DefId { + desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } + separate_provide_extern + } + + query coroutine_hidden_types( + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + desc { "looking up the hidden types stored across await points in a coroutine" } + } + + /// Gets a map with the variances of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::variances_of`] instead. + /// + ///
+ query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { + arena_cache + desc { "computing the variances for items in this crate" } + } + + /// Returns the (inferred) variances of the item given by `DefId`. + /// + /// The list of variances corresponds to the list of (early-bound) generic + /// parameters of the item (including its parents). + /// + /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the + /// result of this query for use in UI tests or for debugging purposes. + query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { + desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + cycle_delay_bug + } + + /// Gets a map with the inferred outlives-predicates of every item in the local crate. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::inferred_outlives_of`] instead. + /// + ///
+ query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> { + arena_cache + desc { "computing the inferred outlives-predicates for items in this crate" } + } + + /// Maps from an impl/trait or struct/variant `DefId` + /// to a list of the `DefId`s of its associated items or fields. + query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { + desc { |tcx| "collecting associated items or fields of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + /// Maps from a trait/impl item to the trait/impl item "descriptor". + query associated_item(key: DefId) -> ty::AssocItem { + desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Collects the associated items defined on a trait or impl. + query associated_items(key: DefId) -> &'tcx ty::AssocItems { + arena_cache + desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } + } + + /// Maps from associated items on a trait to the corresponding associated + /// item on the impl specified by `impl_id`. + /// + /// For example, with the following code + /// + /// ``` + /// struct Type {} + /// // DefId + /// trait Trait { // trait_id + /// fn f(); // trait_f + /// fn g() {} // trait_g + /// } + /// + /// impl Trait for Type { // impl_id + /// fn f() {} // impl_f + /// fn g() {} // impl_g + /// } + /// ``` + /// + /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be + ///`{ trait_f: impl_f, trait_g: impl_g }` + query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap { + arena_cache + desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } + } + + /// Given the `item_def_id` of a trait or impl, return a mapping from associated fn def id + /// to its associated type items that correspond to the RPITITs in its signature. + query associated_types_for_impl_traits_in_trait_or_impl(item_def_id: DefId) -> &'tcx DefIdMap> { + arena_cache + desc { |tcx| "synthesizing RPITIT items for the opaque types for methods in `{}`", tcx.def_path_str(item_def_id) } + separate_provide_extern + } + + /// Given an `impl_id`, return the trait it implements along with some header information. + query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { + desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } + cache_on_disk_if { impl_id.is_local() } + separate_provide_extern + } + + /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due + /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct + /// whose tail is one of those types. + query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool { + desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) } + } + + /// Maps a `DefId` of a type to a list of its inherent impls. + /// Contains implementations of methods that are inherent to a type. + /// Methods in these implementations don't need to be exported. + query inherent_impls(key: DefId) -> &'tcx [DefId] { + desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + desc { |tcx| "collecting all inherent impls for `{:?}`", key } + } + + /// Unsafety-check this `LocalDefId`. + query check_transmutes(key: LocalDefId) { + desc { |tcx| "check transmute calls inside `{}`", tcx.def_path_str(key) } + } + + /// Unsafety-check this `LocalDefId`. + query check_unsafety(key: LocalDefId) { + desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } + } + + /// Checks well-formedness of tail calls (`become f()`). + query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { + desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Returns the types assumed to be well formed while "inside" of the given item. + /// + /// Note that we've liberated the late bound regions of function signatures, so + /// this can not be used to check whether these types are well formed. + query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { + desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } + } + + /// We need to store the assumed_wf_types for an RPITIT so that impls of foreign + /// traits with return-position impl trait in traits can inherit the right wf types. + query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { + desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } + separate_provide_extern + } + + /// Computes the signature of the function. + query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + cycle_delay_bug + } + + /// Performs lint checking for the module. + query lint_mod(key: LocalModDefId) { + desc { |tcx| "linting {}", describe_as_module(key, tcx) } + } + + query check_unused_traits(_: ()) { + desc { "checking unused trait imports in crate" } + } + + /// Checks the attributes in the module. + query check_mod_attrs(key: LocalModDefId) { + desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } + } + + /// 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) } + } + + query check_mod_privacy(key: LocalModDefId) { + desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } + } + + query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet { + arena_cache + desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } + } + + /// Return the live symbols in the crate for dead code check. + /// + /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). + query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( + LocalDefIdSet, + LocalDefIdMap>, + ), ErrorGuaranteed> { + arena_cache + desc { "finding live symbols in crate" } + } + + query check_mod_deathness(key: LocalModDefId) { + desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } + } + + query check_type_wf(key: ()) -> Result<(), ErrorGuaranteed> { + desc { "checking that types are well-formed" } + return_result_from_ensure_ok + } + + /// Caches `CoerceUnsized` kinds for impls on custom types. + query coerce_unsized_info(key: DefId) -> Result { + desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + return_result_from_ensure_ok + } + + query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { + desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } + cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) } + } + + query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { + desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + + query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } + return_result_from_ensure_ok + } + + /// Borrow-checks the given typeck root, e.g. functions, const/static items, + /// and its children, e.g. closures, inline consts. + query mir_borrowck(key: LocalDefId) -> Result< + &'tcx FxIndexMap>, + ErrorGuaranteed + > { + desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } + } + + /// Gets a complete map from all types to their inherent impls. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) { + desc { "finding all inherent impls defined in crate" } + } + + /// Checks all types in the crate for overlap in their inherent impls. Reports errors. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { + desc { "check for inherent impls that should not be defined in crate" } + return_result_from_ensure_ok + } + + /// Checks all types in the crate for overlap in their inherent impls. Reports errors. + /// + ///
+ /// + /// **Not meant to be used** directly outside of coherence. + /// + ///
+ query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { + desc { "check for overlap between inherent impls defined in this crate" } + return_result_from_ensure_ok + } + + /// Checks whether all impls in the crate pass the overlap check, returning + /// which impls fail it. If all impls are correct, the returned slice is empty. + query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| + "checking whether impl `{}` follows the orphan rules", + tcx.def_path_str(key), + } + return_result_from_ensure_ok + } + + /// Return the set of (transitive) callees that may result in a recursive call to `key`, + /// if we were able to walk all callees. + query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option> { + cycle_fatal + arena_cache + desc { |tcx| + "computing (transitive) callees of `{}` that may recurse", + tcx.def_path_str(key), + } + cache_on_disk_if { true } + } + + /// Obtain all the calls into other local functions + query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { + cycle_fatal + desc { |tcx| + "computing all local function calls in `{}`", + tcx.def_path_str(key.def_id()), + } + } + + /// Computes the tag (if any) for a given type and variant. + /// + /// `None` means that the variant doesn't need a tag (because it is niched). + /// + /// # Panics + /// + /// This query will panic for uninhabited variants and if the passed type is not an enum. + query tag_for_variant( + key: PseudoCanonicalInput<'tcx, (Ty<'tcx>, abi::VariantIdx)>, + ) -> Option { + desc { "computing variant tag for enum" } + } + + /// Evaluates a constant and returns the computed allocation. + /// + ///
+ /// + /// **Do not call this query** directly, use [`Self::eval_to_const_value_raw`] or + /// [`Self::eval_to_valtree`] instead. + /// + ///
+ query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) + -> EvalToAllocationRawResult<'tcx> { + desc { |tcx| + "const-evaluating + checking `{}`", + key.value.display(tcx) + } + cache_on_disk_if { true } + } + + /// Evaluate a static's initializer, returning the allocation of the initializer's memory. + query eval_static_initializer(key: DefId) -> EvalStaticInitializerRawResult<'tcx> { + desc { |tcx| + "evaluating initializer of static `{}`", + tcx.def_path_str(key) + } + cache_on_disk_if { key.is_local() } + separate_provide_extern + feedable + } + + /// Evaluates const items or anonymous constants[^1] into a representation + /// suitable for the type system and const generics. + /// + ///
+ /// + /// **Do not call this** directly, use one of the following wrappers: + /// [`TyCtxt::const_eval_poly`], [`TyCtxt::const_eval_resolve`], + /// [`TyCtxt::const_eval_instance`], or [`TyCtxt::const_eval_global_id`]. + /// + ///
+ /// + /// [^1]: Such as enum variant explicit discriminants or array lengths. + query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) + -> EvalToConstValueResult<'tcx> { + desc { |tcx| + "simplifying constant for the type system `{}`", + key.value.display(tcx) + } + depth_limit + cache_on_disk_if { true } + } + + /// Evaluate a constant and convert it to a type level constant or + /// return `None` if that is not possible. + query eval_to_valtree( + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> + ) -> EvalToValTreeResult<'tcx> { + desc { "evaluating type-level constant" } + } + + /// Converts a type-level constant value into a MIR constant value. + query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue { + desc { "converting type-level constant value to MIR constant value"} + } + + // FIXME get rid of this with valtrees + query lit_to_const( + key: LitToConstInput<'tcx> + ) -> ty::Const<'tcx> { + desc { "converting literal to const" } + } + + query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { + desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + /// Performs part of the privacy check and computes effective visibilities. + query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { + eval_always + desc { "checking effective visibilities" } + } + query check_private_in_public(module_def_id: LocalModDefId) { + desc { |tcx| + "checking for private elements in public interfaces for {}", + describe_as_module(module_def_id, tcx) + } + } + + query reachable_set(_: ()) -> &'tcx LocalDefIdSet { + arena_cache + desc { "reachability" } + cache_on_disk_if { true } + } + + /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body; + /// in the case of closures, this will be redirected to the enclosing function. + query region_scope_tree(def_id: DefId) -> &'tcx crate::middle::region::ScopeTree { + desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) } + } + + /// Generates a MIR body for the shim. + query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { + arena_cache + desc { + |tcx| "generating MIR shim for `{}`, instance={:?}", + tcx.def_path_str(key.def_id()), + key + } + } + + /// The `symbol_name` query provides the symbol name for calling a + /// given instance from the local crate. In particular, it will also + /// look up the correct symbol name of instances from upstream crates. + query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> { + desc { "computing the symbol for `{}`", key } + cache_on_disk_if { true } + } + + query def_kind(def_id: DefId) -> DefKind { + desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the definition. + query def_span(def_id: DefId) -> Span { + desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the identifier of the definition. + query def_ident_span(def_id: DefId) -> Option { + desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + /// Gets the span for the type of the definition. + /// Panics if it is not a definition that has a single type. + query ty_span(def_id: LocalDefId) -> Span { + desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + query lookup_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + query lookup_const_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + query lookup_default_body_stability(def_id: DefId) -> Option { + desc { |tcx| "looking up default body stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query should_inherit_track_caller(def_id: DefId) -> bool { + desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } + } + + query inherited_align(def_id: DefId) -> Option { + desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) } + } + + query lookup_deprecation_entry(def_id: DefId) -> Option { + desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Determines whether an item is annotated with `#[doc(hidden)]`. + query is_doc_hidden(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Determines whether an item is annotated with `#[doc(notable_trait)]`. + query is_doc_notable_trait(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } + } + + /// Returns the attributes on the item at `def_id`. + /// + /// Do not use this directly, use `tcx.get_attrs` instead. + query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] { + desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Returns the `CodegenFnAttrs` for the item at `def_id`. + /// + /// If possible, use `tcx.codegen_instance_attrs` instead. That function takes the + /// instance kind into account. + /// + /// For example, the `#[naked]` attribute should be applied for `InstanceKind::Item`, + /// but should not be applied if the instance kind is `InstanceKind::ReifyShim`. + /// Using this query would include the attribute regardless of the actual instance + /// kind at the call site. + query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs { + desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } + arena_cache + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + feedable + } + + query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { + desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } + } + + query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { + desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the rendered value of the specified constant or associated constant. + /// Used by rustdoc. + query rendered_const(def_id: DefId) -> &'tcx String { + arena_cache + desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the rendered precise capturing args for an opaque for use in rustdoc. + query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind]> { + desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query impl_parent(def_id: DefId) -> Option { + desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query is_ctfe_mir_available(key: DefId) -> bool { + desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + query is_mir_available(key: DefId) -> bool { + desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } + + query own_existential_vtable_entries( + key: DefId + ) -> &'tcx [DefId] { + desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } + } + + query vtable_entries(key: ty::TraitRef<'tcx>) + -> &'tcx [ty::VtblEntry<'tcx>] { + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } + } + + query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { + desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() } + } + + query supertrait_vtable_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 } + } + + 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_else(|| "_".to_owned()) + } + } + + query codegen_select_candidate( + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> + ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { + cache_on_disk_if { true } + desc { |tcx| "computing candidate for `{}`", key.value } + } + + /// Return all `impl` blocks in the current crate. + query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap> { + desc { "finding local trait impls" } + } + + /// Return all `impl` blocks of the given trait in the current crate. + query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { + desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } + } + + /// Given a trait `trait_id`, return all known `impl` blocks. + query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { + arena_cache + desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } + } + + query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { + desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } + cache_on_disk_if { true } + return_result_from_ensure_ok + } + query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { + desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } + } + query is_dyn_compatible(trait_id: DefId) -> bool { + desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) } + } + + /// Gets the ParameterEnvironment for a given item; this environment + /// will be in "user-facing" mode, meaning that it is suitable for + /// type-checking etc, and it does not normalize specializable + /// associated types. + /// + /// You should almost certainly not use this. If you already have an InferCtxt, then + /// you should also probably have a `ParamEnv` from when it was built. If you don't, + /// then you should take a `TypingEnv` to ensure that you handle opaque types correctly. + query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { + desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } + feedable + } + + /// Like `param_env`, but returns the `ParamEnv` after all opaque types have been + /// replaced with their hidden type. This is used in the old trait solver + /// when in `PostAnalysis` mode and should not be called directly. + query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> { + desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } + } + + /// 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::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Copy`", env.value } + } + /// Trait selection queries. These are best used by invoking `ty.is_use_cloned_modulo_regions()`, + /// `ty.is_use_cloned()`, etc, since that will prune the environment where possible. + query is_use_cloned_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `UseCloned`", env.value } + } + /// Query backing `Ty::is_sized`. + query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Sized`", env.value } + } + /// Query backing `Ty::is_freeze`. + query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is freeze", env.value } + } + /// Query backing `Ty::is_unpin`. + query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `Unpin`", env.value } + } + /// Query backing `Ty::is_async_drop`. + query is_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` is `AsyncDrop`", env.value } + } + /// Query backing `Ty::needs_drop`. + query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` needs drop", env.value } + } + /// Query backing `Ty::needs_async_drop`. + query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` needs async drop", env.value } + } + /// Query backing `Ty::has_significant_drop_raw`. + query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` has a significant drop", env.value } + } + + /// Query backing `Ty::is_structural_eq_shallow`. + /// + /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types + /// correctly. + query has_structural_eq_impl(ty: Ty<'tcx>) -> bool { + desc { + "computing whether `{}` implements `StructuralPartialEq`", + ty + } + } + + /// A list of types where the ADT requires drop if and only if any of + /// those types require drop. If the ADT is known to always need drop + /// then `Err(AlwaysRequiresDrop)` is returned. + query adt_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` needs drop", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + /// A list of types where the ADT requires async drop if and only if any of + /// those types require async drop. If the ADT is known to always need async drop + /// then `Err(AlwaysRequiresDrop)` is returned. + query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` needs async drop", tcx.def_path_str(def_id) } + cache_on_disk_if { true } + } + + /// A list of types where the ADT requires drop if and only if any of those types + /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor` + /// is considered to not be significant. A drop is significant if it is implemented + /// by the user or does anything that will have any observable behavior (other than + /// freeing up memory). If the ADT is known to have a significant destructor then + /// `Err(AlwaysRequiresDrop)` is returned. + query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } + } + + /// Returns a list of types which (a) have a potentially significant destructor + /// and (b) may be dropped as a result of dropping a value of some type `ty` + /// (in the given environment). + /// + /// The idea of "significant" drop is somewhat informal and is used only for + /// diagnostics and edition migrations. The idea is that a significant drop may have + /// some visible side-effect on execution; freeing memory is NOT considered a side-effect. + /// The rules are as follows: + /// * Type with no explicit drop impl do not have significant drop. + /// * Types with a drop impl are assumed to have significant drop unless they have a `#[rustc_insignificant_dtor]` annotation. + /// + /// Note that insignificant drop is a "shallow" property. A type like `Vec` does not + /// have significant drop but the type `LockGuard` does, and so if `ty = Vec` + /// then the return value would be `&[LockGuard]`. + /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, + /// because this query partially depends on that query. + /// Otherwise, there is a risk of query cycles. + query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { + desc { |tcx| "computing when `{}` has a significant destructor", ty.value } + } + + /// Computes the layout of a type. Note that this implicitly + /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. + query layout_of( + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> + ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { + depth_limit + desc { "computing layout of `{}`", key.value } + // we emit our own error during query cycle handling + cycle_delay_bug + } + + /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. + /// + /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` + /// instead, where the instance is an `InstanceKind::Virtual`. + query fn_abi_of_fn_ptr( + key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}` function pointers", key.value.0 } + } + + /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for + /// direct calls to an `fn`. + /// + /// NB: that includes virtual calls, which are represented by "direct calls" + /// to an `InstanceKind::Virtual` instance (of `::fn`). + query fn_abi_of_instance( + key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> + ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { + desc { "computing call ABI of `{}`", key.value.0 } + } + + query dylib_dependency_formats(_: CrateNum) + -> &'tcx [(CrateNum, LinkagePreference)] { + desc { "getting dylib dependency formats of crate" } + separate_provide_extern + } + + query dependency_formats(_: ()) -> &'tcx Arc { + arena_cache + desc { "getting the linkage format of all dependencies" } + } + + query is_compiler_builtins(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate is_compiler_builtins" } + separate_provide_extern + } + query has_global_allocator(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always + cycle_fatal + desc { "checking if the crate has_global_allocator" } + separate_provide_extern + } + query has_alloc_error_handler(_: CrateNum) -> bool { + // This query depends on untracked global state in CStore + eval_always + cycle_fatal + desc { "checking if the crate has_alloc_error_handler" } + separate_provide_extern + } + query has_panic_handler(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if the crate has_panic_handler" } + separate_provide_extern + } + query is_profiler_runtime(_: CrateNum) -> bool { + cycle_fatal + desc { "checking if a crate is `#![profiler_runtime]`" } + separate_provide_extern + } + query has_ffi_unwind_calls(key: LocalDefId) -> bool { + desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + query required_panic_strategy(_: CrateNum) -> Option { + cycle_fatal + desc { "getting a crate's required panic strategy" } + separate_provide_extern + } + query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { + cycle_fatal + desc { "getting a crate's configured panic-in-drop strategy" } + separate_provide_extern + } + query is_no_builtins(_: CrateNum) -> bool { + cycle_fatal + desc { "getting whether a crate has `#![no_builtins]`" } + separate_provide_extern + } + query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { + cycle_fatal + desc { "getting a crate's symbol mangling version" } + separate_provide_extern + } + + query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> { + eval_always + desc { "getting crate's ExternCrateData" } + separate_provide_extern + } + + query specialization_enabled_in(cnum: CrateNum) -> bool { + desc { "checking whether the crate enabled `specialization`/`min_specialization`" } + separate_provide_extern + } + + query specializes(_: (DefId, DefId)) -> bool { + desc { "computing whether impls specialize one another" } + } + query in_scope_traits_map(_: hir::OwnerId) + -> Option<&'tcx ItemLocalMap>> { + desc { "getting traits in scope at a block" } + } + + /// Returns whether the impl or associated function has the `default` keyword. + /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`. + query defaultness(def_id: DefId) -> hir::Defaultness { + desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + /// Returns whether the field corresponding to the `DefId` has a default field value. + query default_field(def_id: DefId) -> Option { + desc { |tcx| "looking up the `const` corresponding to the default for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + // The `DefId`s of all non-generic functions and statics in the given crate + // that can be reached from outside the crate. + // + // We expect this items to be available for being linked to. + // + // This query can also be called for `LOCAL_CRATE`. In this case it will + // compute which items will be reachable to other crates, taking into account + // the kind of crate that is currently compiled. Crates with only a + // C interface have fewer reachable things. + // + // Does not include external symbols that don't have a corresponding DefId, + // like the compiler-generated `main` function and so on. + query reachable_non_generics(_: CrateNum) + -> &'tcx DefIdMap { + arena_cache + desc { "looking up the exported symbols of a crate" } + separate_provide_extern + } + query is_reachable_non_generic(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + query is_unreachable_local_definition(def_id: LocalDefId) -> bool { + desc { |tcx| + "checking whether `{}` is reachable from outside the crate", + tcx.def_path_str(def_id), + } + } + + /// The entire set of monomorphizations the local crate can safely + /// link to because they are exported from upstream crates. Do + /// not depend on this directly, as its value changes anytime + /// a monomorphization gets added or removed in any upstream + /// crate. Instead use the narrower `upstream_monomorphizations_for`, + /// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or, + /// even better, `Instance::upstream_monomorphization()`. + query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { + arena_cache + desc { "collecting available upstream monomorphizations" } + } + + /// Returns the set of upstream monomorphizations available for the + /// generic function identified by the given `def_id`. The query makes + /// sure to make a stable selection if the same monomorphization is + /// available in multiple upstream crates. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + query upstream_monomorphizations_for(def_id: DefId) + -> Option<&'tcx UnordMap, CrateNum>> + { + desc { |tcx| + "collecting available upstream monomorphizations for `{}`", + tcx.def_path_str(def_id), + } + separate_provide_extern + } + + /// Returns the upstream crate that exports drop-glue for the given + /// type (`args` is expected to be a single-item list containing the + /// type one wants drop-glue for). + /// + /// This is a subset of `upstream_monomorphizations_for` in order to + /// increase dep-tracking granularity. Otherwise adding or removing any + /// type with drop-glue in any upstream crate would invalidate all + /// functions calling drop-glue of an upstream type. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + /// + /// NOTE: This query could easily be extended to also support other + /// common functions that have are large set of monomorphizations + /// (like `Clone::clone` for example). + query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { + desc { "available upstream drop-glue for `{:?}`", args } + } + + /// Returns the upstream crate that exports async-drop-glue for + /// the given type (`args` is expected to be a single-item list + /// containing the type one wants async-drop-glue for). + /// + /// This is a subset of `upstream_monomorphizations_for` in order + /// to increase dep-tracking granularity. Otherwise adding or + /// removing any type with async-drop-glue in any upstream crate + /// would invalidate all functions calling async-drop-glue of an + /// upstream type. + /// + /// You likely want to call `Instance::upstream_monomorphization()` + /// instead of invoking this query directly. + /// + /// NOTE: This query could easily be extended to also support other + /// common functions that have are large set of monomorphizations + /// (like `Clone::clone` for example). + query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { + desc { "available upstream async-drop-glue for `{:?}`", args } + } + + /// Returns a list of all `extern` blocks of a crate. + query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap { + arena_cache + desc { "looking up the foreign modules of a linked crate" } + separate_provide_extern + } + + /// Lint against `extern fn` declarations having incompatible types. + query clashing_extern_declarations(_: ()) { + desc { "checking `extern fn` declarations are compatible" } + } + + /// Identifies the entry-point (e.g., the `main` function) for a given + /// crate, returning `None` if there is no entry point (such as for library crates). + query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { + desc { "looking up the entry function of a crate" } + } + + /// Finds the `rustc_proc_macro_decls` item of a crate. + query proc_macro_decls_static(_: ()) -> Option { + desc { "looking up the proc macro declarations for a crate" } + } + + // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. + // Changing the name should cause a compiler error, but in case that changes, be aware. + // + // The hash should not be calculated before the `analysis` pass is complete, specifically + // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental + // compilation is enabled calculating this hash can freeze this structure too early in + // compilation and cause subsequent crashes when attempting to write to `definitions` + query crate_hash(_: CrateNum) -> Svh { + eval_always + desc { "looking up the hash a crate" } + separate_provide_extern + } + + /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. + query crate_host_hash(_: CrateNum) -> Option { + eval_always + desc { "looking up the hash of a host version of a crate" } + separate_provide_extern + } + + /// Gets the extra data to put in each output filename for a crate. + /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. + query extra_filename(_: CrateNum) -> &'tcx String { + arena_cache + eval_always + desc { "looking up the extra filename for a crate" } + separate_provide_extern + } + + /// Gets the paths where the crate came from in the file system. + query crate_extern_paths(_: CrateNum) -> &'tcx Vec { + arena_cache + eval_always + desc { "looking up the paths for extern crates" } + separate_provide_extern + } + + /// Given a crate and a trait, look up all impls of that trait in the crate. + /// Return `(impl_id, self_ty)`. + query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { + desc { "looking up implementations of a trait in a crate" } + separate_provide_extern + } + + /// Collects all incoherent impls for the given crate and type. + /// + /// Do not call this directly, but instead use the `incoherent_impls` query. + /// This query is only used to get the data necessary for that query. + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + desc { |tcx| "collecting all impls for a type in a crate" } + separate_provide_extern + } + + /// Get the corresponding native library from the `native_libraries` query + query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { + desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } + } + + query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] { + desc { "inheriting delegation signature" } + } + + /// Does lifetime resolution on items. Importantly, we can't resolve + /// lifetimes directly on things like trait methods, because of trait params. + /// See `rustc_resolve::late::lifetimes` for details. + query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars<'tcx> { + arena_cache + desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } + } + query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { + desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } + } + query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { + desc { |tcx| "testing if a region is late bound inside `{}`", tcx.def_path_str(owner_id) } + } + /// Returns the *default lifetime* to be used if a trait object type were to be passed for + /// the type parameter given by `DefId`. + /// + /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically + /// print the result of this query for use in UI tests or for debugging purposes. + /// + /// # Examples + /// + /// - For `T` in `struct Foo<'a, T: 'a>(&'a T);`, this would be `Param('a)` + /// - For `T` in `struct Bar<'a, T>(&'a T);`, this would be `Empty` + /// + /// # Panics + /// + /// This query will panic if the given definition is not a type parameter. + query object_lifetime_default(def_id: DefId) -> ObjectLifetimeDefault { + desc { "looking up lifetime defaults for type parameter `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + query late_bound_vars_map(owner_id: hir::OwnerId) + -> &'tcx SortedMap>> { + desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } + } + /// For an opaque type, return the list of (captured lifetime, inner generic param). + /// ```ignore (illustrative) + /// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into + 'b { ... } + /// ``` + /// + /// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound. + /// + /// After hir_ty_lowering, we get: + /// ```ignore (pseudo-code) + /// opaque foo::<'a>::opaque<'_a, '_b>: Into> + '_b; + /// ^^^^^^^^ inner generic params + /// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b> + /// ^^^^^^ captured lifetimes + /// ``` + query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] { + desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } + } + + /// Computes the visibility of the provided `def_id`. + /// + /// If the item from the `def_id` doesn't have a visibility, it will panic. For example + /// a generic type parameter will panic if you call this method on it: + /// + /// ``` + /// use std::fmt::Debug; + /// + /// pub trait Foo {} + /// ``` + /// + /// In here, if you call `visibility` on `T`, it'll panic. + query visibility(def_id: DefId) -> ty::Visibility { + desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + feedable + } + + query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { + desc { "computing the uninhabited predicate of `{:?}`", key } + } + + /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead. + query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> { + desc { "computing the uninhabited predicate of `{}`", key } + } + + query dep_kind(_: CrateNum) -> CrateDepKind { + eval_always + desc { "fetching what a dependency looks like" } + separate_provide_extern + } + + /// Gets the name of the crate. + query crate_name(_: CrateNum) -> Symbol { + feedable + desc { "fetching what a crate is named" } + separate_provide_extern + } + query module_children(def_id: DefId) -> &'tcx [ModChild] { + desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + /// Gets the number of definitions in a foreign crate. + /// + /// This allows external tools to iterate over all definitions in a foreign crate. + /// + /// This should never be used for the local crate, instead use `iter_local_def_id`. + query num_extern_def_ids(_: CrateNum) -> usize { + desc { "fetching the number of definitions in a crate" } + separate_provide_extern + } + + query lib_features(_: CrateNum) -> &'tcx LibFeatures { + desc { "calculating the lib features defined in a crate" } + separate_provide_extern + arena_cache + } + /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` + /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute + /// exists, then this map will have a `impliee -> implier` entry. + /// + /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should + /// specify their implications (both `implies` and `implied_by`). If only one of the two + /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this + /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is + /// reported, only the `#[stable]` attribute information is available, so the map is necessary + /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` + /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of + /// unstable feature" error for a feature that was implied. + query stability_implications(_: CrateNum) -> &'tcx UnordMap { + arena_cache + desc { "calculating the implications between `#[unstable]` features defined in a crate" } + separate_provide_extern + } + /// Whether the function is an intrinsic + query intrinsic_raw(def_id: DefId) -> Option { + desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) } + separate_provide_extern + } + /// Returns the lang items defined in another crate by loading it from metadata. + query get_lang_items(_: ()) -> &'tcx LanguageItems { + arena_cache + eval_always + desc { "calculating the lang items map" } + } + + /// Returns all diagnostic items defined in all crates. + query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { + arena_cache + eval_always + desc { "calculating the diagnostic items map" } + } + + /// Returns the lang items defined in another crate by loading it from metadata. + query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] { + desc { "calculating the lang items defined in a crate" } + separate_provide_extern + } + + /// Returns the diagnostic items defined in a crate. + query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { + arena_cache + desc { "calculating the diagnostic items map in a crate" } + separate_provide_extern + } + + query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { + desc { "calculating the missing lang items in a crate" } + separate_provide_extern + } + + /// The visible parent map is a map from every item to a visible parent. + /// It prefers the shortest visible path to an item. + /// Used for diagnostics, for example path trimming. + /// The parents are modules, enums or traits. + query visible_parent_map(_: ()) -> &'tcx DefIdMap { + arena_cache + desc { "calculating the visible parent map" } + } + /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. + /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. + query trimmed_def_paths(_: ()) -> &'tcx DefIdMap { + arena_cache + desc { "calculating trimmed def paths" } + } + query missing_extern_crate_item(_: CrateNum) -> bool { + eval_always + desc { "seeing if we're missing an `extern crate` item for this crate" } + separate_provide_extern + } + query used_crate_source(_: CrateNum) -> &'tcx Arc { + arena_cache + eval_always + desc { "looking at the source for a crate" } + separate_provide_extern + } + + /// Returns the debugger visualizers defined for this crate. + /// NOTE: This query has to be marked `eval_always` because it reads data + /// directly from disk that is not tracked anywhere else. I.e. it + /// represents a genuine input to the query system. + query debugger_visualizers(_: CrateNum) -> &'tcx Vec { + arena_cache + desc { "looking up the debugger visualizers for this crate" } + separate_provide_extern + eval_always + } + + query postorder_cnums(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "generating a postorder list of CrateNums" } + } + /// Returns whether or not the crate with CrateNum 'cnum' + /// is marked as a private dependency + query is_private_dep(c: CrateNum) -> bool { + eval_always + desc { "checking whether crate `{}` is a private dependency", c } + separate_provide_extern + } + query allocator_kind(_: ()) -> Option { + eval_always + desc { "getting the allocator kind for the current crate" } + } + query alloc_error_handler_kind(_: ()) -> Option { + eval_always + desc { "alloc error handler kind for the current crate" } + } + + query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { + desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } + } + + /// All available crates in the graph, including those that should not be user-facing + /// (such as private crates). + query crates(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "fetching all foreign CrateNum instances" } + } + + // Crates that are loaded non-speculatively (not for diagnostics or doc links). + // FIXME: This is currently only used for collecting lang items, but should be used instead of + // `crates` in most other cases too. + query used_crates(_: ()) -> &'tcx [CrateNum] { + eval_always + desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } + } + + /// All crates that share the same name as crate `c`. + /// + /// This normally occurs when multiple versions of the same dependency are present in the + /// dependency tree. + query duplicate_crate_names(c: CrateNum) -> &'tcx [CrateNum] { + desc { "fetching `CrateNum`s with same name as `{c:?}`" } + } + + /// A list of all traits in a crate, used by rustdoc and error reporting. + query traits(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all traits in a crate" } + separate_provide_extern + } + + query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all trait impls in a crate" } + separate_provide_extern + } + + query stable_order_of_exportable_impls(_: CrateNum) -> &'tcx FxIndexMap { + desc { "fetching the stable impl's order" } + separate_provide_extern + } + + query exportable_items(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all exportable items in a crate" } + separate_provide_extern + } + + /// The list of non-generic symbols exported from the given crate. + /// + /// This is separate from exported_generic_symbols to avoid having + /// to deserialize all non-generic symbols too for upstream crates + /// in the upstream_monomorphizations query. + /// + /// - All names contained in `exported_non_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported non-generic symbols for crate `{}`", cnum} + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + /// The list of generic symbols exported from the given crate. + /// + /// - All names contained in `exported_generic_symbols(cnum)` are + /// guaranteed to correspond to a publicly visible symbol in `cnum` + /// machine code. + /// - The `exported_non_generic_symbols` and `exported_generic_symbols` + /// sets of different crates do not intersect. + query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { + desc { "collecting exported generic symbols for crate `{}`", cnum} + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } + + query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> { + eval_always + desc { "collect_and_partition_mono_items" } + } + + query is_codegened_item(def_id: DefId) -> bool { + desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } + } + + query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { + desc { "getting codegen unit `{sym}`" } + } + + query backend_optimization_level(_: ()) -> OptLevel { + desc { "optimization level used by backend" } + } + + /// Return the filenames where output artefacts shall be stored. + /// + /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` + /// has been destroyed. + query output_filenames(_: ()) -> &'tcx Arc { + feedable + desc { "getting output filenames" } + arena_cache + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_projection( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_free_alias( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + ///
+ /// + /// Do not call this query directly: Invoke `normalize` instead. + /// + ///
+ query normalize_canonicalized_inherent_projection( + goal: CanonicalAliasGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value } + } + + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_generic_arg_after_erasing_regions( + goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> + ) -> Result, NoSolution> { + desc { "normalizing `{}`", goal.value } + } + + query implied_outlives_bounds( + key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool) + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, + NoSolution, + > { + desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 } + } + + /// Do not call this query directly: + /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. + query dropck_outlives( + goal: CanonicalDropckOutlivesGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, + NoSolution, + > { + desc { "computing dropck types for `{}`", goal.canonical.value.value.dropped_ty } + } + + /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or + /// `infcx.predicate_must_hold()` instead. + query evaluate_obligation( + goal: CanonicalPredicateGoal<'tcx> + ) -> Result { + desc { "evaluating trait selection obligation `{}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `Eq` type-op + query type_op_ascribe_user_type( + goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, + NoSolution, + > { + desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `ProvePredicate` type-op + query type_op_prove_predicate( + goal: CanonicalTypeOpProvePredicateGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, + NoSolution, + > { + desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.canonical.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_ty( + goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_clause( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_poly_fn_sig( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + /// Do not call this query directly: part of the `Normalize` type-op + query type_op_normalize_fn_sig( + goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{:?}`", goal.canonical.value.value.value } + } + + query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { + desc { |tcx| + "checking impossible instantiated predicates: `{}`", + tcx.def_path_str(key.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), + } + } + + query method_autoderef_steps( + goal: CanonicalMethodAutoderefStepsGoal<'tcx> + ) -> MethodAutoderefStepsResult<'tcx> { + desc { "computing autoderef types for `{}`", goal.canonical.value.value.self_ty } + } + + /// Used by `-Znext-solver` to compute proof trees. + query evaluate_root_goal_for_proof_tree_raw( + goal: solve::CanonicalInput<'tcx>, + ) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe>) { + no_hash + desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate } + } + + /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! + query rust_target_features(_: CrateNum) -> &'tcx UnordMap { + arena_cache + eval_always + desc { "looking up Rust target features" } + } + + query implied_target_features(feature: Symbol) -> &'tcx Vec { + arena_cache + eval_always + desc { "looking up implied target features" } + } + + query features_query(_: ()) -> &'tcx rustc_feature::Features { + feedable + desc { "looking up enabled feature gates" } + } + + query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { + feedable + no_hash + desc { "the ast before macro expansion and name resolution" } + } + + /// Attempt to resolve the given `DefId` to an `Instance`, for the + /// given generics args (`GenericArgsRef`), returning one of: + /// * `Ok(Some(instance))` on success + /// * `Ok(None)` when the `GenericArgsRef` are still too generic, + /// and therefore don't allow finding the final `Instance` + /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process + /// couldn't complete due to errors elsewhere - this is distinct + /// from `Ok(None)` to avoid misleading diagnostics when an error + /// has already been/will be emitted, for the original cause. + query resolve_instance_raw( + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> + ) -> Result>, ErrorGuaranteed> { + desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) } + } + + query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { + desc { "revealing opaque types in `{:?}`", key } + } + + query limits(key: ()) -> Limits { + desc { "looking up limits" } + } + + /// Performs an HIR-based well-formed check on the item with the given `HirId`. If + /// we get an `Unimplemented` error that matches the provided `Predicate`, return + /// the cause of the newly created obligation. + /// + /// This is only used by error-reporting code to get a better cause (in particular, a better + /// span) for an *existing* error. Therefore, it is best-effort, and may never handle + /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, + /// because the `ty::Ty`-based wfcheck is always run. + query diagnostic_hir_wf_check( + key: (ty::Predicate<'tcx>, WellFormedLoc) + ) -> Option<&'tcx ObligationCause<'tcx>> { + arena_cache + eval_always + no_hash + desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } + } + + /// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, + /// `--target` and similar). + query global_backend_features(_: ()) -> &'tcx Vec { + arena_cache + eval_always + desc { "computing the backend features for CLI flags" } + } + + query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { + desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } + } + + /// This takes the def-id of an associated item from a impl of a trait, + /// and checks its validity against the trait item it corresponds to. + /// + /// Any other def id will ICE. + query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } + return_result_from_ensure_ok + } + + query deduced_param_attrs(def_id: DefId) -> &'tcx [DeducedParamAttrs] { + desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap { + eval_always + desc { "resolutions for documentation links for a module" } + separate_provide_extern + } + + query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] { + eval_always + desc { "traits in scope for documentation links for a module" } + separate_provide_extern + } + + /// Get all item paths that were stripped by a `#[cfg]` in a particular crate. + /// Should not be called for the local crate before the resolver outputs are created, as it + /// is only fed there. + query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { + desc { "getting cfg-ed out item names" } + separate_provide_extern + } + + query generics_require_sized_self(def_id: DefId) -> bool { + desc { "check whether the item has a `where Self: Sized` bound" } + } + + query cross_crate_inlinable(def_id: DefId) -> bool { + desc { "whether the item should be made inlinable across crates" } + separate_provide_extern + } + + /// Perform monomorphization-time checking on this item. + /// This is used for lints/errors that can only be checked once the instance is fully + /// monomorphized. + query check_mono_item(key: ty::Instance<'tcx>) { + desc { "monomorphization-time checking" } + } + + /// Builds the set of functions that should be skipped for the move-size check. + query skip_move_check_fns(_: ()) -> &'tcx FxIndexSet { + arena_cache + desc { "functions to skip for move-size check" } + } + + query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { + desc { "collecting items used by `{}`", key.0 } + cache_on_disk_if { true } + } + + query size_estimate(key: ty::Instance<'tcx>) -> usize { + desc { "estimating codegen size of `{}`", key } + cache_on_disk_if { true } + } + + query anon_const_kind(def_id: DefId) -> ty::AnonConstKind { + desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + + query trivial_const(def_id: DefId) -> Option<(mir::ConstValue, Ty<'tcx>)> { + desc { |tcx| "checking if `{}` is a trivial const", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } + + /// Checks for the nearest `#[sanitize(xyz = "off")]` or + /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the + /// crate root. + /// + /// Returns the sanitizer settings for this def. + query sanitizer_settings_for(key: LocalDefId) -> SanitizerFnAttrs { + desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } + feedable + } + + query check_externally_implementable_items(_: ()) { + desc { "check externally implementable items" } + } + + /// Returns a list of all `externally implementable items` crate. + query externally_implementable_items(cnum: CrateNum) -> &'tcx FxIndexMap)> { + arena_cache + desc { "looking up the externally implementable items of a crate" } + cache_on_disk_if { *cnum == LOCAL_CRATE } + separate_provide_extern + } +} + +rustc_with_all_queries! { define_callbacks! } +rustc_feedable_queries! { define_feedable! } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 32071595ec28f..99b1f6d8c2515 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -15,7 +15,7 @@ use rustc_span::source_map::Spanned; use crate::mir::interpret::EvalToValTreeResult; use crate::mir::mono::{MonoItem, NormalizationErrorInMono}; -use crate::query::CyclePlaceholder; +use crate::query::plumbing::CyclePlaceholder; use crate::traits::solve; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c9291d89be8aa..24a38e70ff6f2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,148 +1,12 @@ -//! -//! # The rustc Query System: Query Definitions and Modifiers -//! -//! The core processes in rustc are shipped as queries. Each query is a demand-driven function from some key to a value. -//! The execution result of the function is cached and directly read during the next request, thereby improving compilation efficiency. -//! Some results are saved locally and directly read during the next compilation, which are core of incremental compilation. -//! -//! ## How to Read This Module -//! -//! Each `query` block in this file defines a single query, specifying its key and value types, along with various modifiers. -//! These query definitions are processed by the [`rustc_macros`], which expands them into the necessary boilerplate code -//! for the query system—including the [`Providers`] struct (a function table for all query implementations, where each field is -//! a function pointer to the actual provider), caching, and dependency graph integration. -//! **Note:** The `Providers` struct is not a Rust trait, but a struct generated by the `rustc_macros` to hold all provider functions. -//! The `rustc_macros` also supports a set of **query modifiers** (see below) that control the behavior of each query. -//! -//! The actual provider functions are implemented in various modules and registered into the `Providers` struct -//! during compiler initialization (see [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]). -//! -//! [`rustc_macros`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/index.html -//! [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]: ../../rustc_interface/passes/static.DEFAULT_QUERY_PROVIDERS.html -//! -//! ## Query Modifiers -//! -//! Query modifiers are special flags that alter the behavior of a query. They are parsed and processed by the `rustc_macros` -//! The main modifiers are: -//! -//! - `desc { ... }`: Sets the human-readable description for diagnostics and profiling. Required for every query. -//! - `arena_cache`: Use an arena for in-memory caching of the query result. -//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to true. -//! - `cycle_fatal`: If a dependency cycle is detected, abort compilation with a fatal error. -//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. -//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. -//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. -//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). -//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. -//! - `depth_limit`: Impose a recursion depth limit on the query to prevent stack overflows. -//! - `separate_provide_extern`: Use separate provider functions for local and external crates. -//! - `feedable`: Allow the query result to be set from another query ("fed" externally). -//! - `return_result_from_ensure_ok`: When called via `tcx.ensure_ok()`, return `Result<(), ErrorGuaranteed>` instead of `()`. -//! If the query needs to be executed and returns an error, the error is returned to the caller. -//! Only valid for queries returning `Result<_, ErrorGuaranteed>`. -//! -//! For the up-to-date list, see the `QueryModifiers` struct in -//! [`rustc_macros/src/query.rs`](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_macros/src/query.rs) -//! and for more details in incremental compilation, see the -//! [Query modifiers in incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#query-modifiers) section of the rustc-dev-guide. -//! -//! ## Query Expansion and Code Generation -//! -//! The [`rustc_macros::rustc_queries`] macro expands each query definition into: -//! - A method on [`TyCtxt`] (and [`TyCtxtAt`]) for invoking the query. -//! - Provider traits and structs for supplying the query's value. -//! - Caching and dependency graph integration. -//! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. -//! -//! [`rustc_macros::rustc_queries`]: ../../rustc_macros/macro.rustc_queries.html -//! -//! The macro-based approach allows the query system to be highly flexible and maintainable, while minimizing boilerplate. -//! -//! For more details, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). - -#![allow(unused_parens)] - -use std::ffi::OsStr; -use std::mem; -use std::path::PathBuf; -use std::sync::Arc; - -use rustc_abi::Align; -use rustc_arena::TypedArena; -use rustc_ast::expand::allocator::AllocatorKind; -use rustc_ast::tokenstream::TokenStream; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_data_structures::sorted_map::SortedMap; -use rustc_data_structures::steal::Steal; -use rustc_data_structures::svh::Svh; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::{EiiDecl, EiiImpl, StrippedCfgItem}; -use rustc_hir::def::{DefKind, DocLinkResMap}; -use rustc_hir::def_id::{ - CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, -}; -use rustc_hir::lang_items::{LangItem, LanguageItems}; -use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; -use rustc_index::IndexVec; -use rustc_lint_defs::LintId; -use rustc_macros::rustc_queries; -use rustc_query_system::query::{QueryMode, QueryState}; -use rustc_session::Limits; -use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; -use rustc_session::cstore::{ - CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, -}; -use rustc_session::lint::LintExpectationId; -use rustc_span::def_id::LOCAL_CRATE; -use rustc_span::source_map::Spanned; -use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; -use rustc_target::spec::PanicStrategy; -use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; +use rustc_hir::def_id::LocalDefId; +pub use rustc_query_system::query::{QueryMode, QueryState}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; -use crate::infer::canonical::{self, Canonical}; -use crate::lint::LintExpectation; -use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; -use crate::middle::debugger_visualizer::DebuggerVisualizerFile; -use crate::middle::deduced_param_attrs::DeducedParamAttrs; -use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; -use crate::middle::lib_features::LibFeatures; -use crate::middle::privacy::EffectiveVisibilities; -use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; -use crate::middle::stability::DeprecationEntry; -use crate::mir::interpret::{ - EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, - EvalToValTreeResult, GlobalId, LitToConstInput, -}; -use crate::mir::mono::{ - CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, -}; -use crate::query::plumbing::CyclePlaceholder; -use crate::traits::query::{ - CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, - CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, - CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, DropckConstraint, - DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult, - OutlivesBound, -}; -use crate::traits::{ - CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource, - ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph, -}; -use crate::ty::fast_reject::SimplifiedType; -use crate::ty::layout::ValidityRequirement; -use crate::ty::print::PrintTraitRefExt; -use crate::ty::util::AlwaysRequiresDrop; -use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty, - TyCtxt, TyCtxtFeed, -}; -use crate::{dep_graph, mir, thir}; +pub use crate::queries::Providers; +use crate::ty::TyCtxt; -mod arena_cached; +pub(crate) mod arena_cached; pub mod erase; pub(crate) mod inner; mod keys; @@ -150,2641 +14,7 @@ pub mod on_disk_cache; #[macro_use] pub mod plumbing; -// Each of these queries corresponds to a function pointer field in the -// `Providers` struct for requesting a value of that type, and a method -// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way -// which memoizes and does dep-graph tracking, wrapping around the actual -// `Providers` that the driver creates (using several `rustc_*` crates). -// -// The result type of each query must implement `Clone`, and additionally -// `ty::query::values::Value`, which produces an appropriate placeholder -// (error) value if the query resulted in a query cycle. -// Queries marked with `cycle_fatal` do not need the latter implementation, -// as they will raise an fatal error on query cycles instead. -rustc_queries! { - /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`. - /// The key is: - /// - A unique key corresponding to the invocation of a macro. - /// - Token stream which serves as an input to the macro. - /// - /// The output is the token stream generated by the proc macro. - query derive_macro_expansion(key: (LocalExpnId, &'tcx TokenStream)) -> Result<&'tcx TokenStream, ()> { - desc { "expanding a derive (proc) macro" } - cache_on_disk_if { true } - } - - /// This exists purely for testing the interactions between delayed bugs and incremental. - query trigger_delayed_bug(key: DefId) { - desc { "triggering a delayed bug for testing incremental" } - } - - /// Collects the list of all tools registered using `#![register_tool]`. - query registered_tools(_: ()) -> &'tcx ty::RegisteredTools { - arena_cache - desc { "compute registered tools for crate" } - } - - query early_lint_checks(_: ()) { - desc { "perform lints prior to AST lowering" } - } - - /// Tracked access to environment variables. - /// - /// Useful for the implementation of `std::env!`, `proc-macro`s change - /// detection and other changes in the compiler's behaviour that is easier - /// to control with an environment variable than a flag. - /// - /// NOTE: This currently does not work with dependency info in the - /// analysis, codegen and linking passes, place extra code at the top of - /// `rustc_interface::passes::write_dep_info` to make that work. - query env_var_os(key: &'tcx OsStr) -> Option<&'tcx OsStr> { - // Environment variables are global state - eval_always - desc { "get the value of an environment variable" } - } - - query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - desc { "getting the resolver outputs" } - } - - query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc)>, &'tcx ty::ResolverGlobalCtxt) { - eval_always - no_hash - desc { "getting the resolver for lowering" } - } - - /// Return the span for a definition. - /// - /// Contrary to `def_span` below, this query returns the full absolute span of the definition. - /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside - /// of rustc_middle::hir::source_map. - query source_span(key: LocalDefId) -> Span { - // Accesses untracked data - eval_always - desc { "getting the source span" } - } - - /// Represents crate as a whole (as distinct from the top-level crate module). - /// - /// If you call `tcx.hir_crate(())` we will have to assume that any change - /// means that you need to be recompiled. This is because the `hir_crate` - /// query gives you access to all other items. To avoid this fate, do not - /// call `tcx.hir_crate(())`; instead, prefer wrappers like - /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. - query hir_crate(key: ()) -> &'tcx Crate<'tcx> { - arena_cache - eval_always - desc { "getting the crate HIR" } - } - - /// All items in the crate. - query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems { - arena_cache - eval_always - desc { "getting HIR crate items" } - } - - /// The items in a module. - /// - /// This can be conveniently accessed by `tcx.hir_visit_item_likes_in_module`. - /// Avoid calling this query directly. - query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { - arena_cache - desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - - /// Returns HIR ID for the given `LocalDefId`. - query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { - desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to the HIR node's parent for the HIR owner `key`. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query hir_owner_parent_q(key: hir::OwnerId) -> hir::HirId { - desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } - } - - /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { - desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to the HIR attributes inside the HIR owner `key`. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { - desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) } - feedable - } - - /// Gives access to lints emitted during ast lowering. - /// - /// This can be conveniently accessed by `tcx.hir_*` methods. - /// Avoid calling this query directly. - query opt_ast_lowering_delayed_lints(key: hir::OwnerId) -> Option<&'tcx hir::lints::DelayedLints> { - desc { |tcx| "getting AST lowering delayed lints in `{}`", tcx.def_path_str(key) } - } - - /// Returns the *default* of the const pararameter given by `DefId`. - /// - /// E.g., given `struct Ty;` this returns `3` for `N`. - query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { - desc { |tcx| "computing the default for const parameter `{}`", tcx.def_path_str(param) } - cache_on_disk_if { param.is_local() } - separate_provide_extern - } - - /// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`. - /// - /// When a const item is used in a type-level expression, like in equality for an assoc const - /// projection, this allows us to retrieve the typesystem-appropriate representation of the - /// const value. - /// - /// This query will ICE if given a const that is not marked with `#[type_const]`. - query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { - desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Returns the *type* of the definition given by `DefId`. - /// - /// For type aliases (whether eager or lazy) and associated types, this returns - /// the underlying aliased type (not the corresponding [alias type]). - /// - /// For opaque types, this returns and thus reveals the hidden type! If you - /// want to detect cycle errors use `type_of_opaque` instead. - /// - /// To clarify, for type definitions, this does *not* return the "type of a type" - /// (aka *kind* or *sort*) in the type-theoretical sense! It merely returns - /// the type primarily *associated with* it. - /// - /// # Panics - /// - /// This query will panic if the given definition doesn't (and can't - /// conceptually) have an (underlying) type. - /// - /// [alias type]: rustc_middle::ty::AliasTy - query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - desc { |tcx| - "{action} `{path}`", - action = match tcx.def_kind(key) { - DefKind::TyAlias => "expanding type alias", - DefKind::TraitAlias => "expanding trait alias", - _ => "computing type of", - }, - path = tcx.def_path_str(key), - } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. - /// - /// This is a specialized instance of [`Self::type_of`] that detects query cycles. - /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. - /// This is used to improve the error message in cases where revealing the hidden type - /// for auto-trait leakage cycles. - /// - /// # Panics - /// - /// This query will panic if the given definition is not an opaque type. - query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { - desc { |tcx| - "computing type of opaque `{path}`", - path = tcx.def_path_str(key), - } - cycle_stash - } - query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - desc { |tcx| - "computing type of opaque `{path}` via HIR typeck", - path = tcx.def_path_str(key), - } - } - - /// Returns whether the type alias given by `DefId` is lazy. - /// - /// I.e., if the type alias expands / ought to expand to a [free] [alias type] - /// instead of the underlying aliased type. - /// - /// Relevant for features `lazy_type_alias` and `type_alias_impl_trait`. - /// - /// # Panics - /// - /// This query *may* panic if the given definition is not a type alias. - /// - /// [free]: rustc_middle::ty::Free - /// [alias type]: rustc_middle::ty::AliasTy - query type_alias_is_lazy(key: DefId) -> bool { - desc { |tcx| - "computing whether the type alias `{path}` is lazy", - path = tcx.def_path_str(key), - } - separate_provide_extern - } - - query collect_return_position_impl_trait_in_trait_tys(key: DefId) - -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> - { - desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin - { - desc { "determine where the opaque originates from" } - separate_provide_extern - } - - query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet - { - arena_cache - desc { |tcx| - "determining what parameters of `{}` can participate in unsizing", - tcx.def_path_str(key), - } - } - - /// The root query triggering all analysis passes like typeck or borrowck. - query analysis(key: ()) { - eval_always - desc { |tcx| - "running analysis passes on crate `{}`", - tcx.crate_name(LOCAL_CRATE), - } - } - - /// This query checks the fulfillment of collected lint expectations. - /// All lint emitting queries have to be done before this is executed - /// to ensure that all expectations can be fulfilled. - /// - /// This is an extra query to enable other drivers (like rustdoc) to - /// only execute a small subset of the `analysis` query, while allowing - /// lints to be expected. In rustc, this query will be executed as part of - /// the `analysis` query and doesn't have to be called a second time. - /// - /// Tools can additionally pass in a tool filter. That will restrict the - /// expectations to only trigger for lints starting with the listed tool - /// name. This is useful for cases were not all linting code from rustc - /// was called. With the default `None` all registered lints will also - /// be checked for expectation fulfillment. - query check_expectations(key: Option) { - eval_always - desc { "checking lint expectations (RFC 2383)" } - } - - /// Returns the *generics* of the definition given by `DefId`. - query generics_of(key: DefId) -> &'tcx ty::Generics { - desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } - arena_cache - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the (elaborated) *predicates* of the definition given by `DefId` - /// that must be proven true at usage sites (and which can be assumed at definition site). - /// - /// This is almost always *the* "predicates query" that you want. - /// - /// **Tip**: You can use `#[rustc_dump_predicates]` on an item to basically print - /// the result of this query for use in UI tests or for debugging purposes. - query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - } - - query opaque_types_defined_by( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the opaque types defined by `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - - /// A list of all bodies inside of `key`, nested bodies are always stored - /// before their parent. - query nested_bodies_within( - key: LocalDefId - ) -> &'tcx ty::List { - desc { - |tcx| "computing the coroutines defined within `{}`", - tcx.def_path_str(key.to_def_id()) - } - } - - /// Returns the explicitly user-written *bounds* on the associated or opaque type given by `DefId` - /// that must be proven true at definition site (and which can be assumed at usage sites). - /// - /// For associated types, these must be satisfied for an implementation - /// to be well-formed, and for opaque types, these are required to be - /// satisfied by the hidden type of the opaque. - /// - /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. - /// - /// Syntactially, these are the bounds written on associated types in trait - /// definitions, or those after the `impl` keyword for an opaque: - /// - /// ```ignore (illustrative) - /// trait Trait { type X: Bound + 'lt; } - /// // ^^^^^^^^^^^ - /// fn function() -> impl Debug + Display { /*...*/ } - /// // ^^^^^^^^^^^^^^^ - /// ``` - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the explicitly user-written *bounds* that share the `Self` type of the item. - /// - /// These are a subset of the [explicit item bounds] that may explicitly be used for things - /// like closure signature deduction. - /// - /// [explicit item bounds]: Self::explicit_item_bounds - query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the (elaborated) *bounds* on the associated or opaque type given by `DefId` - /// that must be proven true at definition site (and which can be assumed at usage sites). - /// - /// Bounds from the parent (e.g. with nested `impl Trait`) are not included. - /// - /// **Tip**: You can use `#[rustc_dump_item_bounds]` on an item to basically print - /// the result of this query for use in UI tests or for debugging purposes. - /// - /// # Examples - /// - /// ``` - /// trait Trait { type Assoc: Eq + ?Sized; } - /// ``` - /// - /// While [`Self::explicit_item_bounds`] returns `[::Assoc: Eq]` - /// here, `item_bounds` returns: - /// - /// ```text - /// [ - /// ::Assoc: Eq, - /// ::Assoc: PartialEq<::Assoc> - /// ] - /// ``` - query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } - } - - query item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } - } - - query item_non_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } - } - - query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { - desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } - } - - /// Look up all native libraries this crate depends on. - /// These are assembled from the following places: - /// - `extern` blocks (depending on their `link` attributes) - /// - the `libs` (`-l`) option - query native_libraries(_: CrateNum) -> &'tcx Vec { - arena_cache - desc { "looking up the native libraries of a linked crate" } - separate_provide_extern - } - - query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap { - arena_cache - desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) } - } - - query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> { - arena_cache - desc { "computing `#[expect]`ed lints in this crate" } - } - - query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { - arena_cache - desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" } - } - - query expn_that_defined(key: DefId) -> rustc_span::ExpnId { - desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - query is_panic_runtime(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate is_panic_runtime" } - separate_provide_extern - } - - /// Checks whether a type is representable or infinitely sized - query representability(_: LocalDefId) -> rustc_middle::ty::Representability { - desc { "checking if `{}` is representable", tcx.def_path_str(key) } - // infinitely sized types will cause a cycle - cycle_delay_bug - // 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 - anon - } - - /// An implementation detail for the `representability` query - query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability { - desc { "checking if `{}` is representable", key } - cycle_delay_bug - anon - } - - /// Set of param indexes for type params that are in the type's representation - query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet { - desc { "finding type parameters in the representation" } - arena_cache - no_hash - separate_provide_extern - } - - /// Fetch the THIR for a given body. The THIR body gets stolen by unsafety checking unless - /// `-Zno-steal-thir` is on. - query thir_body(key: LocalDefId) -> Result<(&'tcx Steal>, thir::ExprId), ErrorGuaranteed> { - // Perf tests revealed that hashing THIR is inefficient (see #85729). - no_hash - desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) } - } - - /// Set of all the `DefId`s in this crate that have MIR associated with - /// them. This includes all the body owners, but also things like struct - /// constructors. - query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet { - arena_cache - desc { "getting a list of all mir_keys" } - } - - /// Maps DefId's that have an associated `mir::Body` to the result - /// of the MIR const-checking pass. This is the set of qualifs in - /// the final value of a `const`. - query mir_const_qualif(key: DefId) -> mir::ConstQualifs { - desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Build the MIR for a given `DefId` and prepare it for const qualification. - /// - /// See the [rustc dev guide] for more info. - /// - /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html - query mir_built(key: LocalDefId) -> &'tcx Steal> { - desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } - feedable - } - - /// Try to build an abstract representation of the given constant. - query thir_abstract_const( - key: DefId - ) -> Result>>, ErrorGuaranteed> { - desc { - |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), - } - separate_provide_extern - } - - query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> &'tcx Steal> { - no_hash - desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key) } - } - - query mir_for_ctfe( - key: DefId - ) -> &'tcx mir::Body<'tcx> { - desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query mir_promoted(key: LocalDefId) -> ( - &'tcx Steal>, - &'tcx Steal>> - ) { - no_hash - desc { |tcx| "promoting constants in MIR for `{}`", tcx.def_path_str(key) } - } - - query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> { - desc { - |tcx| "finding symbols for captures of closure `{}`", - tcx.def_path_str(key) - } - } - - /// Returns names of captured upvars for closures and coroutines. - /// - /// Here are some examples: - /// - `name__field1__field2` when the upvar is captured by value. - /// - `_ref__name__field` when the upvar is captured by reference. - /// - /// For coroutines this only contains upvars that are shared by all states. - query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec { - arena_cache - desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { - arena_cache - desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that - /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck. - /// - /// However, we replace each free region in the MIR body with a unique region inference - /// variable. As we may rely on structural identity when proving goals this may cause a - /// goal to no longer hold. We store obligations for which this may happen during HIR - /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck - /// encounters an unexpected error. We expect this to result in an error when used and - /// delay a bug if it does not. - query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { - |tcx| "reproving potentially region dependent HIR typeck goals for `{}", - tcx.def_path_str(key) - } - } - - /// MIR after our optimization passes have run. This is MIR that is ready - /// for codegen. This is also the only query that can fetch non-local MIR, at present. - query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { - desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on - /// this def and any enclosing defs, up to the crate root. - /// - /// Returns `false` if `#[coverage(off)]` was found, or `true` if - /// either `#[coverage(on)]` or no coverage attribute was found. - query coverage_attr_on(key: LocalDefId) -> bool { - desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) } - feedable - } - - /// Scans through a function's MIR after MIR optimizations, to prepare the - /// information needed by codegen when `-Cinstrument-coverage` is active. - /// - /// This includes the details of where to insert `llvm.instrprof.increment` - /// intrinsics, and the expression tables to be embedded in the function's - /// coverage metadata. - /// - /// FIXME(Zalathar): This query's purpose has drifted a bit and should - /// probably be renamed, but that can wait until after the potential - /// follow-ups to #136053 have settled down. - /// - /// Returns `None` for functions that were not instrumented. - query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { - desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } - arena_cache - } - - /// The `DefId` is the `DefId` of the containing MIR body. Promoteds do not have their own - /// `DefId`. This function returns all promoteds in the specified body. The body references - /// promoteds by the `DefId` and the `mir::Promoted` index. This is necessary, because - /// after inlining a body may refer to promoteds from other bodies. In that case you still - /// need to use the `DefId` of the original body. - query promoted_mir(key: DefId) -> &'tcx IndexVec> { - desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Erases regions from `ty` to yield a new type. - /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`, - /// however, which uses this query as a kind of cache. - query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> { - // This query is not expected to have input -- as a result, it - // is not a good candidates for "replay" because it is essentially a - // pure function of its input (and hence the expectation is that - // no caller would be green **apart** from just these - // queries). Making it anonymous avoids hashing the result, which - // may save a bit of time. - anon - desc { "erasing regions from `{}`", ty } - } - - query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap { - arena_cache - desc { "getting wasm import module map" } - } - - /// Returns the explicitly user-written *predicates and bounds* of the trait given by `DefId`. - /// - /// Traits are unusual, because predicates on associated types are - /// converted into bounds on that type for backwards compatibility: - /// - /// ``` - /// trait X where Self::U: Copy { type U; } - /// ``` - /// - /// becomes - /// - /// ``` - /// trait X { type U: Copy; } - /// ``` - /// - /// [`Self::explicit_predicates_of`] and [`Self::explicit_item_bounds`] will - /// then take the appropriate subsets of the predicates here. - /// - /// # Panics - /// - /// This query will panic if the given definition is not a trait. - query trait_explicit_predicates_and_bounds(key: LocalDefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing explicit predicates of trait `{}`", tcx.def_path_str(key) } - } - - /// Returns the explicitly user-written *predicates* of the definition given by `DefId` - /// that must be proven true at usage sites (and which can be assumed at definition site). - /// - /// You should probably use [`Self::predicates_of`] unless you're looking for - /// predicates with explicit spans for diagnostics purposes. - query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { - desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the *inferred outlives-predicates* of the item given by `DefId`. - /// - /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. - /// - /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the - /// result of this query for use in UI tests or for debugging purposes. - query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { - desc { |tcx| "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Returns the explicitly user-written *super-predicates* of the trait given by `DefId`. - /// - /// These predicates are unelaborated and consequently don't contain transitive super-predicates. - /// - /// This is a subset of the full list of predicates. We store these in a separate map - /// because we must evaluate them even during type conversion, often before the full - /// predicates are available (note that super-predicates must not be cyclic). - query explicit_super_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// The predicates of the trait that are implied during elaboration. - /// - /// This is a superset of the super-predicates of the trait, but a subset of the predicates - /// of the trait. For regular traits, this includes all super-predicates and their - /// associated type bounds. For trait aliases, currently, this includes all of the - /// predicates of the trait alias. - query explicit_implied_predicates_of(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// The Ident is the name of an associated type.The query returns only the subset - /// of supertraits that define the given associated type. This is used to avoid - /// cycles in resolving type-dependent associated item paths like `T::Item`. - query explicit_supertraits_containing_assoc_item( - key: (DefId, rustc_span::Ident) - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the super traits of `{}` with associated type name `{}`", - tcx.def_path_str(key.0), - key.1 - } - } - - /// Compute the conditions that need to hold for a conditionally-const item to be const. - /// That is, compute the set of `[const]` where clauses for a given item. - /// - /// This can be thought of as the `[const]` equivalent of `predicates_of`. These are the - /// predicates that need to be proven at usage sites, and can be assumed at definition. - /// - /// This query also computes the `[const]` where clauses for associated types, which are - /// not "const", but which have item bounds which may be `[const]`. These must hold for - /// the `[const]` item bound to hold. - query const_conditions( - key: DefId - ) -> ty::ConstConditions<'tcx> { - desc { |tcx| "computing the conditions for `{}` to be considered const", - tcx.def_path_str(key) - } - separate_provide_extern - } - - /// Compute the const bounds that are implied for a conditionally-const item. - /// - /// This can be though of as the `[const]` equivalent of `explicit_item_bounds`. These - /// are the predicates that need to proven at definition sites, and can be assumed at - /// usage sites. - query explicit_implied_const_bounds( - key: DefId - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> { - desc { |tcx| "computing the implied `[const]` bounds for `{}`", - tcx.def_path_str(key) - } - separate_provide_extern - } - - /// 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::Ident) - ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir_ty_param_name(key.1) } - } - - query trait_def(key: DefId) -> &'tcx ty::TraitDef { - desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } - arena_cache - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_def(key: DefId) -> ty::AdtDef<'tcx> { - desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_destructor(key: DefId) -> Option { - desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_async_destructor(key: DefId) -> Option { - desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query adt_sizedness_constraint( - key: (DefId, SizedTraitKind) - ) -> Option>> { - desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) } - } - - query adt_dtorck_constraint( - key: DefId - ) -> &'tcx DropckConstraint<'tcx> { - desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } - } - - /// Returns the constness of the function-like[^1] definition given by `DefId`. - /// - /// Tuple struct/variant constructors are *always* const, foreign functions are - /// *never* const. The rest is const iff marked with keyword `const` (or rather - /// its parent in the case of associated functions). - /// - ///
- /// - /// **Do not call this query** directly. It is only meant to cache the base data for the - /// higher-level functions. Consider using `is_const_fn` or `is_const_trait_impl` instead. - /// - /// Also note that neither of them takes into account feature gates, stability and - /// const predicates/conditions! - /// - ///
- /// - /// # Panics - /// - /// This query will panic if the given definition is not function-like[^1]. - /// - /// [^1]: Tuple struct/variant constructors, closures and free, associated and foreign functions. - query constness(key: DefId) -> hir::Constness { - desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } - separate_provide_extern - feedable - } - - query asyncness(key: DefId) -> ty::Asyncness { - desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - /// Returns `true` if calls to the function may be promoted. - /// - /// This is either because the function is e.g., a tuple-struct or tuple-variant - /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should - /// be removed in the future in favour of some form of check which figures out whether the - /// function does not inspect the bits of any of its arguments (so is essentially just a - /// constructor function). - query is_promotable_const_fn(key: DefId) -> bool { - desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } - } - - /// The body of the coroutine, modified to take its upvars by move rather than by ref. - /// - /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which - /// is run right after building the initial MIR, and will only be populated for coroutines - /// which come out of the async closure desugaring. - query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { - desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. - query coroutine_kind(def_id: DefId) -> Option { - desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - query coroutine_for_closure(def_id: DefId) -> DefId { - desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } - separate_provide_extern - } - - query coroutine_hidden_types( - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { - desc { "looking up the hidden types stored across await points in a coroutine" } - } - - /// Gets a map with the variances of every item in the local crate. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::variances_of`] instead. - /// - ///
- query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { - arena_cache - desc { "computing the variances for items in this crate" } - } - - /// Returns the (inferred) variances of the item given by `DefId`. - /// - /// The list of variances corresponds to the list of (early-bound) generic - /// parameters of the item (including its parents). - /// - /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the - /// result of this query for use in UI tests or for debugging purposes. - query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { - desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - cycle_delay_bug - } - - /// Gets a map with the inferred outlives-predicates of every item in the local crate. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::inferred_outlives_of`] instead. - /// - ///
- query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> { - arena_cache - desc { "computing the inferred outlives-predicates for items in this crate" } - } - - /// Maps from an impl/trait or struct/variant `DefId` - /// to a list of the `DefId`s of its associated items or fields. - query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { - desc { |tcx| "collecting associated items or fields of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - /// Maps from a trait/impl item to the trait/impl item "descriptor". - query associated_item(key: DefId) -> ty::AssocItem { - desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> &'tcx ty::AssocItems { - arena_cache - desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } - } - - /// Maps from associated items on a trait to the corresponding associated - /// item on the impl specified by `impl_id`. - /// - /// For example, with the following code - /// - /// ``` - /// struct Type {} - /// // DefId - /// trait Trait { // trait_id - /// fn f(); // trait_f - /// fn g() {} // trait_g - /// } - /// - /// impl Trait for Type { // impl_id - /// fn f() {} // impl_f - /// fn g() {} // impl_g - /// } - /// ``` - /// - /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be - ///`{ trait_f: impl_f, trait_g: impl_g }` - query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap { - arena_cache - desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) } - } - - /// Given the `item_def_id` of a trait or impl, return a mapping from associated fn def id - /// to its associated type items that correspond to the RPITITs in its signature. - query associated_types_for_impl_traits_in_trait_or_impl(item_def_id: DefId) -> &'tcx DefIdMap> { - arena_cache - desc { |tcx| "synthesizing RPITIT items for the opaque types for methods in `{}`", tcx.def_path_str(item_def_id) } - separate_provide_extern - } - - /// Given an `impl_id`, return the trait it implements along with some header information. - query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { - desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } - cache_on_disk_if { impl_id.is_local() } - separate_provide_extern - } - - /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due - /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct - /// whose tail is one of those types. - query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool { - desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) } - } - - /// Maps a `DefId` of a type to a list of its inherent impls. - /// Contains implementations of methods that are inherent to a type. - /// Methods in these implementations don't need to be exported. - query inherent_impls(key: DefId) -> &'tcx [DefId] { - desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { - desc { |tcx| "collecting all inherent impls for `{:?}`", key } - } - - /// Unsafety-check this `LocalDefId`. - query check_transmutes(key: LocalDefId) { - desc { |tcx| "check transmute calls inside `{}`", tcx.def_path_str(key) } - } - - /// Unsafety-check this `LocalDefId`. - query check_unsafety(key: LocalDefId) { - desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } - } - - /// Checks well-formedness of tail calls (`become f()`). - query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { - desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Returns the types assumed to be well formed while "inside" of the given item. - /// - /// Note that we've liberated the late bound regions of function signatures, so - /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { - desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } - } - - /// We need to store the assumed_wf_types for an RPITIT so that impls of foreign - /// traits with return-position impl trait in traits can inherit the right wf types. - query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { - desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } - separate_provide_extern - } - - /// Computes the signature of the function. - query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { - desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - cycle_delay_bug - } - - /// Performs lint checking for the module. - query lint_mod(key: LocalModDefId) { - desc { |tcx| "linting {}", describe_as_module(key, tcx) } - } - - query check_unused_traits(_: ()) { - desc { "checking unused trait imports in crate" } - } - - /// Checks the attributes in the module. - query check_mod_attrs(key: LocalModDefId) { - desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } - } - - /// 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) } - } - - query check_mod_privacy(key: LocalModDefId) { - desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } - } - - query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet { - arena_cache - desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) } - cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } - } - - /// Return the live symbols in the crate for dead code check. - /// - /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). - query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( - LocalDefIdSet, - LocalDefIdMap>, - ), ErrorGuaranteed> { - arena_cache - desc { "finding live symbols in crate" } - } - - query check_mod_deathness(key: LocalModDefId) { - desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } - } - - query check_type_wf(key: ()) -> Result<(), ErrorGuaranteed> { - desc { "checking that types are well-formed" } - return_result_from_ensure_ok - } - - /// Caches `CoerceUnsized` kinds for impls on custom types. - query coerce_unsized_info(key: DefId) -> Result { - desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - return_result_from_ensure_ok - } - - query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { - desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if(tcx) { !tcx.is_typeck_child(key.to_def_id()) } - } - - query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet { - desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - - query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } - return_result_from_ensure_ok - } - - /// Borrow-checks the given typeck root, e.g. functions, const/static items, - /// and its children, e.g. closures, inline consts. - query mir_borrowck(key: LocalDefId) -> Result< - &'tcx FxIndexMap>, - ErrorGuaranteed - > { - desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } - } - - /// Gets a complete map from all types to their inherent impls. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) { - desc { "finding all inherent impls defined in crate" } - } - - /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { - desc { "check for inherent impls that should not be defined in crate" } - return_result_from_ensure_ok - } - - /// Checks all types in the crate for overlap in their inherent impls. Reports errors. - /// - ///
- /// - /// **Not meant to be used** directly outside of coherence. - /// - ///
- query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { - desc { "check for overlap between inherent impls defined in this crate" } - return_result_from_ensure_ok - } - - /// Checks whether all impls in the crate pass the overlap check, returning - /// which impls fail it. If all impls are correct, the returned slice is empty. - query orphan_check_impl(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| - "checking whether impl `{}` follows the orphan rules", - tcx.def_path_str(key), - } - return_result_from_ensure_ok - } - - /// Return the set of (transitive) callees that may result in a recursive call to `key`, - /// if we were able to walk all callees. - query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option> { - cycle_fatal - arena_cache - desc { |tcx| - "computing (transitive) callees of `{}` that may recurse", - tcx.def_path_str(key), - } - cache_on_disk_if { true } - } - - /// Obtain all the calls into other local functions - query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { - cycle_fatal - desc { |tcx| - "computing all local function calls in `{}`", - tcx.def_path_str(key.def_id()), - } - } - - /// Computes the tag (if any) for a given type and variant. - /// - /// `None` means that the variant doesn't need a tag (because it is niched). - /// - /// # Panics - /// - /// This query will panic for uninhabited variants and if the passed type is not an enum. - query tag_for_variant( - key: PseudoCanonicalInput<'tcx, (Ty<'tcx>, abi::VariantIdx)>, - ) -> Option { - desc { "computing variant tag for enum" } - } - - /// Evaluates a constant and returns the computed allocation. - /// - ///
- /// - /// **Do not call this query** directly, use [`Self::eval_to_const_value_raw`] or - /// [`Self::eval_to_valtree`] instead. - /// - ///
- query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) - -> EvalToAllocationRawResult<'tcx> { - desc { |tcx| - "const-evaluating + checking `{}`", - key.value.display(tcx) - } - cache_on_disk_if { true } - } - - /// Evaluate a static's initializer, returning the allocation of the initializer's memory. - query eval_static_initializer(key: DefId) -> EvalStaticInitializerRawResult<'tcx> { - desc { |tcx| - "evaluating initializer of static `{}`", - tcx.def_path_str(key) - } - cache_on_disk_if { key.is_local() } - separate_provide_extern - feedable - } - - /// Evaluates const items or anonymous constants[^1] into a representation - /// suitable for the type system and const generics. - /// - ///
- /// - /// **Do not call this** directly, use one of the following wrappers: - /// [`TyCtxt::const_eval_poly`], [`TyCtxt::const_eval_resolve`], - /// [`TyCtxt::const_eval_instance`], or [`TyCtxt::const_eval_global_id`]. - /// - ///
- /// - /// [^1]: Such as enum variant explicit discriminants or array lengths. - query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) - -> EvalToConstValueResult<'tcx> { - desc { |tcx| - "simplifying constant for the type system `{}`", - key.value.display(tcx) - } - depth_limit - cache_on_disk_if { true } - } - - /// Evaluate a constant and convert it to a type level constant or - /// return `None` if that is not possible. - query eval_to_valtree( - key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> - ) -> EvalToValTreeResult<'tcx> { - desc { "evaluating type-level constant" } - } - - /// Converts a type-level constant value into a MIR constant value. - query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue { - desc { "converting type-level constant value to MIR constant value"} - } - - // FIXME get rid of this with valtrees - query lit_to_const( - key: LitToConstInput<'tcx> - ) -> ty::Const<'tcx> { - desc { "converting literal to const" } - } - - query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { - desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - /// Performs part of the privacy check and computes effective visibilities. - query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities { - eval_always - desc { "checking effective visibilities" } - } - query check_private_in_public(module_def_id: LocalModDefId) { - desc { |tcx| - "checking for private elements in public interfaces for {}", - describe_as_module(module_def_id, tcx) - } - } - - query reachable_set(_: ()) -> &'tcx LocalDefIdSet { - arena_cache - desc { "reachability" } - cache_on_disk_if { true } - } - - /// Per-body `region::ScopeTree`. The `DefId` should be the owner `DefId` for the body; - /// in the case of closures, this will be redirected to the enclosing function. - query region_scope_tree(def_id: DefId) -> &'tcx crate::middle::region::ScopeTree { - desc { |tcx| "computing drop scopes for `{}`", tcx.def_path_str(def_id) } - } - - /// Generates a MIR body for the shim. - query mir_shims(key: ty::InstanceKind<'tcx>) -> &'tcx mir::Body<'tcx> { - arena_cache - desc { - |tcx| "generating MIR shim for `{}`, instance={:?}", - tcx.def_path_str(key.def_id()), - key - } - } - - /// The `symbol_name` query provides the symbol name for calling a - /// given instance from the local crate. In particular, it will also - /// look up the correct symbol name of instances from upstream crates. - query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName<'tcx> { - desc { "computing the symbol for `{}`", key } - cache_on_disk_if { true } - } - - query def_kind(def_id: DefId) -> DefKind { - desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the definition. - query def_span(def_id: DefId) -> Span { - desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the identifier of the definition. - query def_ident_span(def_id: DefId) -> Option { - desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - /// Gets the span for the type of the definition. - /// Panics if it is not a definition that has a single type. - query ty_span(def_id: LocalDefId) -> Span { - desc { |tcx| "looking up span for `{}`'s type", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - query lookup_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - query lookup_const_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - query lookup_default_body_stability(def_id: DefId) -> Option { - desc { |tcx| "looking up default body stability of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query should_inherit_track_caller(def_id: DefId) -> bool { - desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) } - } - - query inherited_align(def_id: DefId) -> Option { - desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) } - } - - query lookup_deprecation_entry(def_id: DefId) -> Option { - desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Determines whether an item is annotated with `#[doc(hidden)]`. - query is_doc_hidden(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Determines whether an item is annotated with `#[doc(notable_trait)]`. - query is_doc_notable_trait(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } - } - - /// Returns the attributes on the item at `def_id`. - /// - /// Do not use this directly, use `tcx.get_attrs` instead. - query attrs_for_def(def_id: DefId) -> &'tcx [hir::Attribute] { - desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Returns the `CodegenFnAttrs` for the item at `def_id`. - /// - /// If possible, use `tcx.codegen_instance_attrs` instead. That function takes the - /// instance kind into account. - /// - /// For example, the `#[naked]` attribute should be applied for `InstanceKind::Item`, - /// but should not be applied if the instance kind is `InstanceKind::ReifyShim`. - /// Using this query would include the attribute regardless of the actual instance - /// kind at the call site. - query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs { - desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) } - arena_cache - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - feedable - } - - query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { - desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } - } - - query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { - desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the rendered value of the specified constant or associated constant. - /// Used by rustdoc. - query rendered_const(def_id: DefId) -> &'tcx String { - arena_cache - desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the rendered precise capturing args for an opaque for use in rustdoc. - query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind]> { - desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query impl_parent(def_id: DefId) -> Option { - desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query is_ctfe_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - query is_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } - - query own_existential_vtable_entries( - key: DefId - ) -> &'tcx [DefId] { - desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } - } - - query vtable_entries(key: ty::TraitRef<'tcx>) - -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } - } - - query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { - desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() } - } - - query supertrait_vtable_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 } - } - - 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_else(|| "_".to_owned()) - } - } - - query codegen_select_candidate( - key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> - ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { - cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.value } - } - - /// Return all `impl` blocks in the current crate. - query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap> { - desc { "finding local trait impls" } - } - - /// Return all `impl` blocks of the given trait in the current crate. - query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] { - desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) } - } - - /// Given a trait `trait_id`, return all known `impl` blocks. - query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { - arena_cache - desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) } - } - - query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { - desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } - cache_on_disk_if { true } - return_result_from_ensure_ok - } - query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { - desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } - } - query is_dyn_compatible(trait_id: DefId) -> bool { - desc { |tcx| "checking if trait `{}` is dyn-compatible", tcx.def_path_str(trait_id) } - } - - /// Gets the ParameterEnvironment for a given item; this environment - /// will be in "user-facing" mode, meaning that it is suitable for - /// type-checking etc, and it does not normalize specializable - /// associated types. - /// - /// You should almost certainly not use this. If you already have an InferCtxt, then - /// you should also probably have a `ParamEnv` from when it was built. If you don't, - /// then you should take a `TypingEnv` to ensure that you handle opaque types correctly. - query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> { - desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) } - feedable - } - - /// Like `param_env`, but returns the `ParamEnv` after all opaque types have been - /// replaced with their hidden type. This is used in the old trait solver - /// when in `PostAnalysis` mode and should not be called directly. - query typing_env_normalized_for_post_analysis(def_id: DefId) -> ty::TypingEnv<'tcx> { - desc { |tcx| "computing revealed normalized predicates of `{}`", tcx.def_path_str(def_id) } - } - - /// 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::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Copy`", env.value } - } - /// Trait selection queries. These are best used by invoking `ty.is_use_cloned_modulo_regions()`, - /// `ty.is_use_cloned()`, etc, since that will prune the environment where possible. - query is_use_cloned_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `UseCloned`", env.value } - } - /// Query backing `Ty::is_sized`. - query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Sized`", env.value } - } - /// Query backing `Ty::is_freeze`. - query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is freeze", env.value } - } - /// Query backing `Ty::is_unpin`. - query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `Unpin`", env.value } - } - /// Query backing `Ty::is_async_drop`. - query is_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is `AsyncDrop`", env.value } - } - /// Query backing `Ty::needs_drop`. - query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` needs drop", env.value } - } - /// Query backing `Ty::needs_async_drop`. - query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` needs async drop", env.value } - } - /// Query backing `Ty::has_significant_drop_raw`. - query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` has a significant drop", env.value } - } - - /// Query backing `Ty::is_structural_eq_shallow`. - /// - /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types - /// correctly. - query has_structural_eq_impl(ty: Ty<'tcx>) -> bool { - desc { - "computing whether `{}` implements `StructuralPartialEq`", - ty - } - } - - /// A list of types where the ADT requires drop if and only if any of - /// those types require drop. If the ADT is known to always need drop - /// then `Err(AlwaysRequiresDrop)` is returned. - query adt_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` needs drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - /// A list of types where the ADT requires async drop if and only if any of - /// those types require async drop. If the ADT is known to always need async drop - /// then `Err(AlwaysRequiresDrop)` is returned. - query adt_async_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` needs async drop", tcx.def_path_str(def_id) } - cache_on_disk_if { true } - } - - /// A list of types where the ADT requires drop if and only if any of those types - /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor` - /// is considered to not be significant. A drop is significant if it is implemented - /// by the user or does anything that will have any observable behavior (other than - /// freeing up memory). If the ADT is known to have a significant destructor then - /// `Err(AlwaysRequiresDrop)` is returned. - query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List>, AlwaysRequiresDrop> { - desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } - } - - /// Returns a list of types which (a) have a potentially significant destructor - /// and (b) may be dropped as a result of dropping a value of some type `ty` - /// (in the given environment). - /// - /// The idea of "significant" drop is somewhat informal and is used only for - /// diagnostics and edition migrations. The idea is that a significant drop may have - /// some visible side-effect on execution; freeing memory is NOT considered a side-effect. - /// The rules are as follows: - /// * Type with no explicit drop impl do not have significant drop. - /// * Types with a drop impl are assumed to have significant drop unless they have a `#[rustc_insignificant_dtor]` annotation. - /// - /// Note that insignificant drop is a "shallow" property. A type like `Vec` does not - /// have significant drop but the type `LockGuard` does, and so if `ty = Vec` - /// then the return value would be `&[LockGuard]`. - /// *IMPORTANT*: *DO NOT* run this query before promoted MIR body is constructed, - /// because this query partially depends on that query. - /// Otherwise, there is a risk of query cycles. - query list_significant_drop_tys(ty: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> &'tcx ty::List> { - desc { |tcx| "computing when `{}` has a significant destructor", ty.value } - } - - /// Computes the layout of a type. Note that this implicitly - /// executes in `TypingMode::PostAnalysis`, and will normalize the input type. - query layout_of( - key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> - ) -> Result, &'tcx ty::layout::LayoutError<'tcx>> { - depth_limit - desc { "computing layout of `{}`", key.value } - // we emit our own error during query cycle handling - cycle_delay_bug - } - - /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. - /// - /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` - /// instead, where the instance is an `InstanceKind::Virtual`. - query fn_abi_of_fn_ptr( - key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> - ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}` function pointers", key.value.0 } - } - - /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for - /// direct calls to an `fn`. - /// - /// NB: that includes virtual calls, which are represented by "direct calls" - /// to an `InstanceKind::Virtual` instance (of `::fn`). - query fn_abi_of_instance( - key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> - ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { - desc { "computing call ABI of `{}`", key.value.0 } - } - - query dylib_dependency_formats(_: CrateNum) - -> &'tcx [(CrateNum, LinkagePreference)] { - desc { "getting dylib dependency formats of crate" } - separate_provide_extern - } - - query dependency_formats(_: ()) -> &'tcx Arc { - arena_cache - desc { "getting the linkage format of all dependencies" } - } - - query is_compiler_builtins(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate is_compiler_builtins" } - separate_provide_extern - } - query has_global_allocator(_: CrateNum) -> bool { - // This query depends on untracked global state in CStore - eval_always - cycle_fatal - desc { "checking if the crate has_global_allocator" } - separate_provide_extern - } - query has_alloc_error_handler(_: CrateNum) -> bool { - // This query depends on untracked global state in CStore - eval_always - cycle_fatal - desc { "checking if the crate has_alloc_error_handler" } - separate_provide_extern - } - query has_panic_handler(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if the crate has_panic_handler" } - separate_provide_extern - } - query is_profiler_runtime(_: CrateNum) -> bool { - cycle_fatal - desc { "checking if a crate is `#![profiler_runtime]`" } - separate_provide_extern - } - query has_ffi_unwind_calls(key: LocalDefId) -> bool { - desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) } - cache_on_disk_if { true } - } - query required_panic_strategy(_: CrateNum) -> Option { - cycle_fatal - desc { "getting a crate's required panic strategy" } - separate_provide_extern - } - query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { - cycle_fatal - desc { "getting a crate's configured panic-in-drop strategy" } - separate_provide_extern - } - query is_no_builtins(_: CrateNum) -> bool { - cycle_fatal - desc { "getting whether a crate has `#![no_builtins]`" } - separate_provide_extern - } - query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { - cycle_fatal - desc { "getting a crate's symbol mangling version" } - separate_provide_extern - } - - query extern_crate(def_id: CrateNum) -> Option<&'tcx ExternCrate> { - eval_always - desc { "getting crate's ExternCrateData" } - separate_provide_extern - } - - query specialization_enabled_in(cnum: CrateNum) -> bool { - desc { "checking whether the crate enabled `specialization`/`min_specialization`" } - separate_provide_extern - } - - query specializes(_: (DefId, DefId)) -> bool { - desc { "computing whether impls specialize one another" } - } - query in_scope_traits_map(_: hir::OwnerId) - -> Option<&'tcx ItemLocalMap>> { - desc { "getting traits in scope at a block" } - } - - /// Returns whether the impl or associated function has the `default` keyword. - /// Note: This will ICE on inherent impl items. Consider using `AssocItem::defaultness`. - query defaultness(def_id: DefId) -> hir::Defaultness { - desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - /// Returns whether the field corresponding to the `DefId` has a default field value. - query default_field(def_id: DefId) -> Option { - desc { |tcx| "looking up the `const` corresponding to the default for `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - // The `DefId`s of all non-generic functions and statics in the given crate - // that can be reached from outside the crate. - // - // We expect this items to be available for being linked to. - // - // This query can also be called for `LOCAL_CRATE`. In this case it will - // compute which items will be reachable to other crates, taking into account - // the kind of crate that is currently compiled. Crates with only a - // C interface have fewer reachable things. - // - // Does not include external symbols that don't have a corresponding DefId, - // like the compiler-generated `main` function and so on. - query reachable_non_generics(_: CrateNum) - -> &'tcx DefIdMap { - arena_cache - desc { "looking up the exported symbols of a crate" } - separate_provide_extern - } - query is_reachable_non_generic(def_id: DefId) -> bool { - desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - query is_unreachable_local_definition(def_id: LocalDefId) -> bool { - desc { |tcx| - "checking whether `{}` is reachable from outside the crate", - tcx.def_path_str(def_id), - } - } - - /// The entire set of monomorphizations the local crate can safely - /// link to because they are exported from upstream crates. Do - /// not depend on this directly, as its value changes anytime - /// a monomorphization gets added or removed in any upstream - /// crate. Instead use the narrower `upstream_monomorphizations_for`, - /// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or, - /// even better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { - arena_cache - desc { "collecting available upstream monomorphizations" } - } - - /// Returns the set of upstream monomorphizations available for the - /// generic function identified by the given `def_id`. The query makes - /// sure to make a stable selection if the same monomorphization is - /// available in multiple upstream crates. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx UnordMap, CrateNum>> - { - desc { |tcx| - "collecting available upstream monomorphizations for `{}`", - tcx.def_path_str(def_id), - } - separate_provide_extern - } - - /// Returns the upstream crate that exports drop-glue for the given - /// type (`args` is expected to be a single-item list containing the - /// type one wants drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order to - /// increase dep-tracking granularity. Otherwise adding or removing any - /// type with drop-glue in any upstream crate would invalidate all - /// functions calling drop-glue of an upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream drop-glue for `{:?}`", args } - } - - /// Returns the upstream crate that exports async-drop-glue for - /// the given type (`args` is expected to be a single-item list - /// containing the type one wants async-drop-glue for). - /// - /// This is a subset of `upstream_monomorphizations_for` in order - /// to increase dep-tracking granularity. Otherwise adding or - /// removing any type with async-drop-glue in any upstream crate - /// would invalidate all functions calling async-drop-glue of an - /// upstream type. - /// - /// You likely want to call `Instance::upstream_monomorphization()` - /// instead of invoking this query directly. - /// - /// NOTE: This query could easily be extended to also support other - /// common functions that have are large set of monomorphizations - /// (like `Clone::clone` for example). - query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option { - desc { "available upstream async-drop-glue for `{:?}`", args } - } - - /// Returns a list of all `extern` blocks of a crate. - query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap { - arena_cache - desc { "looking up the foreign modules of a linked crate" } - separate_provide_extern - } - - /// Lint against `extern fn` declarations having incompatible types. - query clashing_extern_declarations(_: ()) { - desc { "checking `extern fn` declarations are compatible" } - } - - /// Identifies the entry-point (e.g., the `main` function) for a given - /// crate, returning `None` if there is no entry point (such as for library crates). - query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { - desc { "looking up the entry function of a crate" } - } - - /// Finds the `rustc_proc_macro_decls` item of a crate. - query proc_macro_decls_static(_: ()) -> Option { - desc { "looking up the proc macro declarations for a crate" } - } - - // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. - // Changing the name should cause a compiler error, but in case that changes, be aware. - // - // The hash should not be calculated before the `analysis` pass is complete, specifically - // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental - // compilation is enabled calculating this hash can freeze this structure too early in - // compilation and cause subsequent crashes when attempting to write to `definitions` - query crate_hash(_: CrateNum) -> Svh { - eval_always - desc { "looking up the hash a crate" } - separate_provide_extern - } - - /// Gets the hash for the host proc macro. Used to support -Z dual-proc-macro. - query crate_host_hash(_: CrateNum) -> Option { - eval_always - desc { "looking up the hash of a host version of a crate" } - separate_provide_extern - } - - /// Gets the extra data to put in each output filename for a crate. - /// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file. - query extra_filename(_: CrateNum) -> &'tcx String { - arena_cache - eval_always - desc { "looking up the extra filename for a crate" } - separate_provide_extern - } - - /// Gets the paths where the crate came from in the file system. - query crate_extern_paths(_: CrateNum) -> &'tcx Vec { - arena_cache - eval_always - desc { "looking up the paths for extern crates" } - separate_provide_extern - } - - /// Given a crate and a trait, look up all impls of that trait in the crate. - /// Return `(impl_id, self_ty)`. - query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { - desc { "looking up implementations of a trait in a crate" } - separate_provide_extern - } - - /// Collects all incoherent impls for the given crate and type. - /// - /// Do not call this directly, but instead use the `incoherent_impls` query. - /// This query is only used to get the data necessary for that query. - query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { - desc { |tcx| "collecting all impls for a type in a crate" } - separate_provide_extern - } - - /// Get the corresponding native library from the `native_libraries` query - query native_library(def_id: DefId) -> Option<&'tcx NativeLib> { - desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } - } - - query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] { - desc { "inheriting delegation signature" } - } - - /// Does lifetime resolution on items. Importantly, we can't resolve - /// lifetimes directly on things like trait methods, because of trait params. - /// See `rustc_resolve::late::lifetimes` for details. - query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars<'tcx> { - arena_cache - desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } - } - query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { - desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } - } - query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { - desc { |tcx| "testing if a region is late bound inside `{}`", tcx.def_path_str(owner_id) } - } - /// Returns the *default lifetime* to be used if a trait object type were to be passed for - /// the type parameter given by `DefId`. - /// - /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically - /// print the result of this query for use in UI tests or for debugging purposes. - /// - /// # Examples - /// - /// - For `T` in `struct Foo<'a, T: 'a>(&'a T);`, this would be `Param('a)` - /// - For `T` in `struct Bar<'a, T>(&'a T);`, this would be `Empty` - /// - /// # Panics - /// - /// This query will panic if the given definition is not a type parameter. - query object_lifetime_default(def_id: DefId) -> ObjectLifetimeDefault { - desc { "looking up lifetime defaults for type parameter `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - query late_bound_vars_map(owner_id: hir::OwnerId) - -> &'tcx SortedMap>> { - desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } - } - /// For an opaque type, return the list of (captured lifetime, inner generic param). - /// ```ignore (illustrative) - /// fn foo<'a: 'a, 'b, T>(&'b u8) -> impl Into + 'b { ... } - /// ``` - /// - /// We would return `[('a, '_a), ('b, '_b)]`, with `'a` early-bound and `'b` late-bound. - /// - /// After hir_ty_lowering, we get: - /// ```ignore (pseudo-code) - /// opaque foo::<'a>::opaque<'_a, '_b>: Into> + '_b; - /// ^^^^^^^^ inner generic params - /// fn foo<'a>: for<'b> fn(&'b u8) -> foo::<'a>::opaque::<'a, 'b> - /// ^^^^^^ captured lifetimes - /// ``` - query opaque_captured_lifetimes(def_id: LocalDefId) -> &'tcx [(ResolvedArg, LocalDefId)] { - desc { |tcx| "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } - } - - /// Computes the visibility of the provided `def_id`. - /// - /// If the item from the `def_id` doesn't have a visibility, it will panic. For example - /// a generic type parameter will panic if you call this method on it: - /// - /// ``` - /// use std::fmt::Debug; - /// - /// pub trait Foo {} - /// ``` - /// - /// In here, if you call `visibility` on `T`, it'll panic. - query visibility(def_id: DefId) -> ty::Visibility { - desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - feedable - } - - query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> { - desc { "computing the uninhabited predicate of `{:?}`", key } - } - - /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead. - query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> { - desc { "computing the uninhabited predicate of `{}`", key } - } - - query dep_kind(_: CrateNum) -> CrateDepKind { - eval_always - desc { "fetching what a dependency looks like" } - separate_provide_extern - } - - /// Gets the name of the crate. - query crate_name(_: CrateNum) -> Symbol { - feedable - desc { "fetching what a crate is named" } - separate_provide_extern - } - query module_children(def_id: DefId) -> &'tcx [ModChild] { - desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - /// Gets the number of definitions in a foreign crate. - /// - /// This allows external tools to iterate over all definitions in a foreign crate. - /// - /// This should never be used for the local crate, instead use `iter_local_def_id`. - query num_extern_def_ids(_: CrateNum) -> usize { - desc { "fetching the number of definitions in a crate" } - separate_provide_extern - } - - query lib_features(_: CrateNum) -> &'tcx LibFeatures { - desc { "calculating the lib features defined in a crate" } - separate_provide_extern - arena_cache - } - /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` - /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute - /// exists, then this map will have a `impliee -> implier` entry. - /// - /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should - /// specify their implications (both `implies` and `implied_by`). If only one of the two - /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this - /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is - /// reported, only the `#[stable]` attribute information is available, so the map is necessary - /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` - /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of - /// unstable feature" error for a feature that was implied. - query stability_implications(_: CrateNum) -> &'tcx UnordMap { - arena_cache - desc { "calculating the implications between `#[unstable]` features defined in a crate" } - separate_provide_extern - } - /// Whether the function is an intrinsic - query intrinsic_raw(def_id: DefId) -> Option { - desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) } - separate_provide_extern - } - /// Returns the lang items defined in another crate by loading it from metadata. - query get_lang_items(_: ()) -> &'tcx LanguageItems { - arena_cache - eval_always - desc { "calculating the lang items map" } - } - - /// Returns all diagnostic items defined in all crates. - query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { - arena_cache - eval_always - desc { "calculating the diagnostic items map" } - } - - /// Returns the lang items defined in another crate by loading it from metadata. - query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] { - desc { "calculating the lang items defined in a crate" } - separate_provide_extern - } - - /// Returns the diagnostic items defined in a crate. - query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems { - arena_cache - desc { "calculating the diagnostic items map in a crate" } - separate_provide_extern - } - - query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { - desc { "calculating the missing lang items in a crate" } - separate_provide_extern - } - - /// The visible parent map is a map from every item to a visible parent. - /// It prefers the shortest visible path to an item. - /// Used for diagnostics, for example path trimming. - /// The parents are modules, enums or traits. - query visible_parent_map(_: ()) -> &'tcx DefIdMap { - arena_cache - desc { "calculating the visible parent map" } - } - /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. - /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. - query trimmed_def_paths(_: ()) -> &'tcx DefIdMap { - arena_cache - desc { "calculating trimmed def paths" } - } - query missing_extern_crate_item(_: CrateNum) -> bool { - eval_always - desc { "seeing if we're missing an `extern crate` item for this crate" } - separate_provide_extern - } - query used_crate_source(_: CrateNum) -> &'tcx Arc { - arena_cache - eval_always - desc { "looking at the source for a crate" } - separate_provide_extern - } - - /// Returns the debugger visualizers defined for this crate. - /// NOTE: This query has to be marked `eval_always` because it reads data - /// directly from disk that is not tracked anywhere else. I.e. it - /// represents a genuine input to the query system. - query debugger_visualizers(_: CrateNum) -> &'tcx Vec { - arena_cache - desc { "looking up the debugger visualizers for this crate" } - separate_provide_extern - eval_always - } - - query postorder_cnums(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "generating a postorder list of CrateNums" } - } - /// Returns whether or not the crate with CrateNum 'cnum' - /// is marked as a private dependency - query is_private_dep(c: CrateNum) -> bool { - eval_always - desc { "checking whether crate `{}` is a private dependency", c } - separate_provide_extern - } - query allocator_kind(_: ()) -> Option { - eval_always - desc { "getting the allocator kind for the current crate" } - } - query alloc_error_handler_kind(_: ()) -> Option { - eval_always - desc { "alloc error handler kind for the current crate" } - } - - query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { - desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } - } - - /// All available crates in the graph, including those that should not be user-facing - /// (such as private crates). - query crates(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "fetching all foreign CrateNum instances" } - } - - // Crates that are loaded non-speculatively (not for diagnostics or doc links). - // FIXME: This is currently only used for collecting lang items, but should be used instead of - // `crates` in most other cases too. - query used_crates(_: ()) -> &'tcx [CrateNum] { - eval_always - desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } - } - - /// All crates that share the same name as crate `c`. - /// - /// This normally occurs when multiple versions of the same dependency are present in the - /// dependency tree. - query duplicate_crate_names(c: CrateNum) -> &'tcx [CrateNum] { - desc { "fetching `CrateNum`s with same name as `{c:?}`" } - } - - /// A list of all traits in a crate, used by rustdoc and error reporting. - query traits(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all traits in a crate" } - separate_provide_extern - } - - query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all trait impls in a crate" } - separate_provide_extern - } - - query stable_order_of_exportable_impls(_: CrateNum) -> &'tcx FxIndexMap { - desc { "fetching the stable impl's order" } - separate_provide_extern - } - - query exportable_items(_: CrateNum) -> &'tcx [DefId] { - desc { "fetching all exportable items in a crate" } - separate_provide_extern - } - - /// The list of non-generic symbols exported from the given crate. - /// - /// This is separate from exported_generic_symbols to avoid having - /// to deserialize all non-generic symbols too for upstream crates - /// in the upstream_monomorphizations query. - /// - /// - All names contained in `exported_non_generic_symbols(cnum)` are - /// guaranteed to correspond to a publicly visible symbol in `cnum` - /// machine code. - /// - The `exported_non_generic_symbols` and `exported_generic_symbols` - /// sets of different crates do not intersect. - query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "collecting exported non-generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } - - /// The list of generic symbols exported from the given crate. - /// - /// - All names contained in `exported_generic_symbols(cnum)` are - /// guaranteed to correspond to a publicly visible symbol in `cnum` - /// machine code. - /// - The `exported_non_generic_symbols` and `exported_generic_symbols` - /// sets of different crates do not intersect. - query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { - desc { "collecting exported generic symbols for crate `{}`", cnum} - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } - - query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> { - eval_always - desc { "collect_and_partition_mono_items" } - } - - query is_codegened_item(def_id: DefId) -> bool { - desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } - } - - query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { - desc { "getting codegen unit `{sym}`" } - } - - query backend_optimization_level(_: ()) -> OptLevel { - desc { "optimization level used by backend" } - } - - /// Return the filenames where output artefacts shall be stored. - /// - /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` - /// has been destroyed. - query output_filenames(_: ()) -> &'tcx Arc { - feedable - desc { "getting output filenames" } - arena_cache - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_projection( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_free_alias( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - ///
- /// - /// Do not call this query directly: Invoke `normalize` instead. - /// - ///
- query normalize_canonicalized_inherent_projection( - goal: CanonicalAliasGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value } - } - - /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. - query try_normalize_generic_arg_after_erasing_regions( - goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> - ) -> Result, NoSolution> { - desc { "normalizing `{}`", goal.value } - } - - query implied_outlives_bounds( - key: (CanonicalImpliedOutlivesBoundsGoal<'tcx>, bool) - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, - NoSolution, - > { - desc { "computing implied outlives bounds for `{}` (hack disabled = {:?})", key.0.canonical.value.value.ty, key.1 } - } - - /// Do not call this query directly: - /// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead. - query dropck_outlives( - goal: CanonicalDropckOutlivesGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, - NoSolution, - > { - desc { "computing dropck types for `{}`", goal.canonical.value.value.dropped_ty } - } - - /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or - /// `infcx.predicate_must_hold()` instead. - query evaluate_obligation( - goal: CanonicalPredicateGoal<'tcx> - ) -> Result { - desc { "evaluating trait selection obligation `{}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `Eq` type-op - query type_op_ascribe_user_type( - goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `ProvePredicate` type-op - query type_op_prove_predicate( - goal: CanonicalTypeOpProvePredicateGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution, - > { - desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.canonical.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_ty( - goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_clause( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_poly_fn_sig( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - /// Do not call this query directly: part of the `Normalize` type-op - query type_op_normalize_fn_sig( - goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, - NoSolution, - > { - desc { "normalizing `{:?}`", goal.canonical.value.value.value } - } - - query instantiate_and_check_impossible_predicates(key: (DefId, GenericArgsRef<'tcx>)) -> bool { - desc { |tcx| - "checking impossible instantiated predicates: `{}`", - tcx.def_path_str(key.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), - } - } - - query method_autoderef_steps( - goal: CanonicalMethodAutoderefStepsGoal<'tcx> - ) -> MethodAutoderefStepsResult<'tcx> { - desc { "computing autoderef types for `{}`", goal.canonical.value.value.self_ty } - } - - /// Used by `-Znext-solver` to compute proof trees. - query evaluate_root_goal_for_proof_tree_raw( - goal: solve::CanonicalInput<'tcx>, - ) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe>) { - no_hash - desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate } - } - - /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! - query rust_target_features(_: CrateNum) -> &'tcx UnordMap { - arena_cache - eval_always - desc { "looking up Rust target features" } - } - - query implied_target_features(feature: Symbol) -> &'tcx Vec { - arena_cache - eval_always - desc { "looking up implied target features" } - } - - query features_query(_: ()) -> &'tcx rustc_feature::Features { - feedable - desc { "looking up enabled feature gates" } - } - - query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { - feedable - no_hash - desc { "the ast before macro expansion and name resolution" } - } - - /// Attempt to resolve the given `DefId` to an `Instance`, for the - /// given generics args (`GenericArgsRef`), returning one of: - /// * `Ok(Some(instance))` on success - /// * `Ok(None)` when the `GenericArgsRef` are still too generic, - /// and therefore don't allow finding the final `Instance` - /// * `Err(ErrorGuaranteed)` when the `Instance` resolution process - /// couldn't complete due to errors elsewhere - this is distinct - /// from `Ok(None)` to avoid misleading diagnostics when an error - /// has already been/will be emitted, for the original cause. - query resolve_instance_raw( - key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> - ) -> Result>, ErrorGuaranteed> { - desc { "resolving instance `{}`", ty::Instance::new_raw(key.value.0, key.value.1) } - } - - query reveal_opaque_types_in_bounds(key: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> { - desc { "revealing opaque types in `{:?}`", key } - } - - query limits(key: ()) -> Limits { - desc { "looking up limits" } - } - - /// Performs an HIR-based well-formed check on the item with the given `HirId`. If - /// we get an `Unimplemented` error that matches the provided `Predicate`, return - /// the cause of the newly created obligation. - /// - /// This is only used by error-reporting code to get a better cause (in particular, a better - /// span) for an *existing* error. Therefore, it is best-effort, and may never handle - /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, - /// because the `ty::Ty`-based wfcheck is always run. - query diagnostic_hir_wf_check( - key: (ty::Predicate<'tcx>, WellFormedLoc) - ) -> Option<&'tcx ObligationCause<'tcx>> { - arena_cache - eval_always - no_hash - desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 } - } - - /// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, - /// `--target` and similar). - query global_backend_features(_: ()) -> &'tcx Vec { - arena_cache - eval_always - desc { "computing the backend features for CLI flags" } - } - - query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result> { - desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } - } - - /// This takes the def-id of an associated item from a impl of a trait, - /// and checks its validity against the trait item it corresponds to. - /// - /// Any other def id will ICE. - query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } - return_result_from_ensure_ok - } - - query deduced_param_attrs(def_id: DefId) -> &'tcx [DeducedParamAttrs] { - desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap { - eval_always - desc { "resolutions for documentation links for a module" } - separate_provide_extern - } - - query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] { - eval_always - desc { "traits in scope for documentation links for a module" } - separate_provide_extern - } - - /// Get all item paths that were stripped by a `#[cfg]` in a particular crate. - /// Should not be called for the local crate before the resolver outputs are created, as it - /// is only fed there. - query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { - desc { "getting cfg-ed out item names" } - separate_provide_extern - } - - query generics_require_sized_self(def_id: DefId) -> bool { - desc { "check whether the item has a `where Self: Sized` bound" } - } - - query cross_crate_inlinable(def_id: DefId) -> bool { - desc { "whether the item should be made inlinable across crates" } - separate_provide_extern - } - - /// Perform monomorphization-time checking on this item. - /// This is used for lints/errors that can only be checked once the instance is fully - /// monomorphized. - query check_mono_item(key: ty::Instance<'tcx>) { - desc { "monomorphization-time checking" } - } - - /// Builds the set of functions that should be skipped for the move-size check. - query skip_move_check_fns(_: ()) -> &'tcx FxIndexSet { - arena_cache - desc { "functions to skip for move-size check" } - } - - query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> Result<(&'tcx [Spanned>], &'tcx [Spanned>]), NormalizationErrorInMono> { - desc { "collecting items used by `{}`", key.0 } - cache_on_disk_if { true } - } - - query size_estimate(key: ty::Instance<'tcx>) -> usize { - desc { "estimating codegen size of `{}`", key } - cache_on_disk_if { true } - } - - query anon_const_kind(def_id: DefId) -> ty::AnonConstKind { - desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) } - separate_provide_extern - } - - query trivial_const(def_id: DefId) -> Option<(mir::ConstValue, Ty<'tcx>)> { - desc { |tcx| "checking if `{}` is a trivial const", tcx.def_path_str(def_id) } - cache_on_disk_if { def_id.is_local() } - separate_provide_extern - } - - /// Checks for the nearest `#[sanitize(xyz = "off")]` or - /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the - /// crate root. - /// - /// Returns the sanitizer settings for this def. - query sanitizer_settings_for(key: LocalDefId) -> SanitizerFnAttrs { - desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } - feedable - } - - query check_externally_implementable_items(_: ()) { - desc { "check externally implementable items" } - } - - /// Returns a list of all `externally implementable items` crate. - query externally_implementable_items(cnum: CrateNum) -> &'tcx FxIndexMap)> { - arena_cache - desc { "looking up the externally implementable items of a crate" } - cache_on_disk_if { *cnum == LOCAL_CRATE } - separate_provide_extern - } -} - -rustc_with_all_queries! { define_callbacks! } -rustc_feedable_queries! { define_feedable! } - -fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { +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() diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 78879dc9da9a9..0b7dc30927194 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -12,10 +12,10 @@ pub use sealed::IntoQueryParam; use crate::dep_graph; use crate::dep_graph::DepKind; -use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use crate::query::{ +use crate::queries::{ ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates, }; +use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use crate::ty::TyCtxt; pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; @@ -189,8 +189,8 @@ macro_rules! query_ensure_select { } macro_rules! query_helper_param_ty { - (DefId) => { impl IntoQueryParam }; - (LocalDefId) => { impl IntoQueryParam }; + (DefId) => { impl $crate::query::IntoQueryParam }; + (LocalDefId) => { impl $crate::query::IntoQueryParam }; ($K:ty) => { $K }; } @@ -213,7 +213,7 @@ macro_rules! local_key_if_separate_extern { $($K)* }; ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => { - <$($K)* as AsLocalKey>::LocalKey + <$($K)* as $crate::query::AsLocalKey>::LocalKey }; ([$other:tt $($modifiers:tt)*] $($K:tt)*) => { local_key_if_separate_extern!([$($modifiers)*] $($K)*) @@ -227,8 +227,8 @@ macro_rules! separate_provide_extern_decl { ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { for<'tcx> fn( TyCtxt<'tcx>, - queries::$name::Key<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx> + $name::Key<'tcx>, + ) -> $name::ProvidedValue<'tcx> }; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { separate_provide_extern_decl!([$($modifiers)*][$($args)*]) @@ -266,94 +266,90 @@ macro_rules! define_callbacks { [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { - - #[allow(unused_lifetimes)] - pub mod queries { - $(pub mod $name { - use super::super::*; - use $crate::query::erase::{self, Erased}; - - pub type Key<'tcx> = $($K)*; - pub type Value<'tcx> = $V; - - pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); - - /// 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 `::Provided` instead. - pub type ProvidedValue<'tcx> = query_if_arena!( - [$($modifiers)*] - (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) - ($V) + $(#[allow(unused_lifetimes)] pub mod $name { + use super::*; + use $crate::query::erase::{self, Erased}; + + pub type Key<'tcx> = $($K)*; + pub type Value<'tcx> = $V; + + pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); + + /// 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 `::Provided` instead. + pub type ProvidedValue<'tcx> = query_if_arena!( + [$($modifiers)*] + (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) + ($V) + ); + + /// This function takes `ProvidedValue` and converts it to an erased `Value` by + /// allocating it on an arena if the query has the `arena_cache` modifier. The + /// value is then erased and returned. This will happen when computing the query + /// using a provider or decoding a stored result. + #[inline(always)] + pub fn provided_to_erased<'tcx>( + _tcx: TyCtxt<'tcx>, + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // Store the provided value in an arena and get a reference + // to it, for queries with `arena_cache`. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] + { + use $crate::query::arena_cached::ArenaCached; + + if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.query_system.arenas.$name.alloc(v), + provided_value, + ) + } else { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.arena.dropless.alloc(v), + provided_value, + ) + } + } + // Otherwise, the provided value is the value. + (provided_value) ); + erase::erase_val(value) + } - /// This function takes `ProvidedValue` and converts it to an erased `Value` by - /// allocating it on an arena if the query has the `arena_cache` modifier. The - /// value is then erased and returned. This will happen when computing the query - /// using a provider or decoding a stored result. - #[inline(always)] - pub fn provided_to_erased<'tcx>( - _tcx: TyCtxt<'tcx>, - provided_value: ProvidedValue<'tcx>, - ) -> Erased> { - // Store the provided value in an arena and get a reference - // to it, for queries with `arena_cache`. - let value: Value<'tcx> = query_if_arena!([$($modifiers)*] - { - use $crate::query::arena_cached::ArenaCached; - - if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.query_system.arenas.$name.alloc(v), - provided_value, - ) - } else { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.arena.dropless.alloc(v), - provided_value, - ) - } - } - // Otherwise, the provided value is the value. - (provided_value) - ); - erase::erase_val(value) + pub type Storage<'tcx> = <$($K)* as $crate::query::Key>::Cache>; + + // Ensure that keys grow no larger than 88 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + const _: () = { + if size_of::>() > 88 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a key type `", + stringify!($($K)*), + "` that is too large" + )); } - - pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; - - // Ensure that keys grow no larger than 88 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - const _: () = { - if size_of::>() > 88 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a key type `", - stringify!($($K)*), - "` that is too large" - )); - } - }; - - // Ensure that values grow no larger than 64 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - #[cfg(not(feature = "rustc_randomized_layouts"))] - const _: () = { - if size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a value type `", - stringify!($V), - "` that is too large" - )); - } - }; - })* - } + }; + + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] + const _: () = { + if size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a value type `", + stringify!($V), + "` that is too large" + )); + } + }; + })* /// Holds per-query arenas for queries with the `arena_cache` modifier. #[derive(Default)] @@ -371,10 +367,10 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryCaches<'tcx> { - $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)* + $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* } - impl<'tcx> TyCtxtEnsureOk<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name( @@ -386,13 +382,13 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), false, ) })* } - impl<'tcx> TyCtxtEnsureDone<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { @@ -400,7 +396,7 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), true, ); })* @@ -416,7 +412,7 @@ macro_rules! define_callbacks { })* } - impl<'tcx> TyCtxtAt<'tcx> { + impl<'tcx> $crate::query::TyCtxtAt<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V @@ -428,7 +424,7 @@ macro_rules! define_callbacks { self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, self.span, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), )) })* } @@ -438,22 +434,22 @@ macro_rules! define_callbacks { /// ("Per" just makes this pluralized name more visually distinct.) pub struct PerQueryVTables<'tcx> { $( - pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, queries::$name::Storage<'tcx>>, + pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Storage<'tcx>>, )* } #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<'tcx, $($K)*>, + pub $name: $crate::query::QueryState<'tcx, $($K)*>, )* } pub struct Providers { $(pub $name: for<'tcx> fn( TyCtxt<'tcx>, - queries::$name::LocalKey<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx>,)* + $name::LocalKey<'tcx>, + ) -> $name::ProvidedValue<'tcx>,)* } pub struct ExternProviders { @@ -490,8 +486,8 @@ macro_rules! define_callbacks { $(pub $name: for<'tcx> fn( TyCtxt<'tcx>, Span, - queries::$name::Key<'tcx>, - QueryMode, + $name::Key<'tcx>, + $crate::query::QueryMode, ) -> Option<$crate::query::erase::Erased<$V>>,)* } }; @@ -499,14 +495,14 @@ macro_rules! define_callbacks { macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(impl<'tcx, K: $crate::query::IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { $(#[$attr])* #[inline(always)] - pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) { + pub fn $name(self, value: $name::ProvidedValue<'tcx>) { let key = self.key().into_query_param(); let tcx = self.tcx; - let erased_value = queries::$name::provided_to_erased(tcx, value); + let erased_value = $name::provided_to_erased(tcx, value); let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index d5076a278eabf..0bbe3856033b7 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -2,7 +2,7 @@ pub mod bug; #[derive(Default, Copy, Clone)] pub struct Providers { - pub queries: crate::query::Providers, - pub extern_queries: crate::query::ExternProviders, + pub queries: crate::queries::Providers, + pub extern_queries: crate::queries::ExternProviders, pub hooks: crate::hooks::Providers, } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index bd69c99a32dc0..baa37111c8070 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -13,11 +13,12 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; +use rustc_middle::queries::{ + self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, +}; +use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::{ - AsLocalKey, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, queries, -}; use rustc_middle::ty::TyCtxt; use rustc_query_system::Value; use rustc_query_system::dep_graph::SerializedDepNodeIndex; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d1721f1f455f7..9ffea692df3a3 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -648,7 +648,7 @@ macro_rules! define_queries { query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(::rustc_middle::query::cached::$name) + Some(queries::cached::$name) } { None }), @@ -672,7 +672,7 @@ macro_rules! define_queries { try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, prev_index, index| { // Check the `cache_on_disk_if` condition for this key. - if !::rustc_middle::query::cached::$name(tcx, key) { + if !queries::cached::$name(tcx, key) { return None; } @@ -687,7 +687,7 @@ macro_rules! define_queries { }), is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, index| -> bool { - ::rustc_middle::query::cached::$name(tcx, key) && + ::rustc_middle::queries::cached::$name(tcx, key) && $crate::plumbing::loadable_from_disk(tcx, index) }) } { @@ -747,7 +747,7 @@ macro_rules! define_queries { let make_frame = |tcx, key| { let kind = rustc_middle::dep_graph::dep_kinds::$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, queries::descs::$name, key, kind, name) }; // Call `gather_active_jobs_inner` to do the actual work. @@ -817,8 +817,8 @@ macro_rules! define_queries { } } - pub fn make_query_vtables<'tcx>() -> ::rustc_middle::query::PerQueryVTables<'tcx> { - ::rustc_middle::query::PerQueryVTables { + pub fn make_query_vtables<'tcx>() -> queries::PerQueryVTables<'tcx> { + queries::PerQueryVTables { $( $name: query_impl::$name::make_query_vtable(), )* diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index a562d0ccd3df3..ea2dab614ec16 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -37,7 +37,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_interface::Config; use rustc_interface::interface::Compiler; -use rustc_middle::query::queries::mir_borrowck::ProvidedValue; +use rustc_middle::queries::mir_borrowck::ProvidedValue; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session;