2 use crate::infer::canonical::{self, Canonical};
3 use crate::lint::LintExpectation;
4 use crate::metadata::ModChild;
5 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
6 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
7 use crate::middle::lib_features::LibFeatures;
8 use crate::middle::privacy::EffectiveVisibilities;
9 use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
10 use crate::middle::stability::{self, DeprecationEntry};
12 use crate::mir::interpret::GlobalId;
13 use crate::mir::interpret::{
14 ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
16 use crate::mir::interpret::{LitToConstError, LitToConstInput};
17 use crate::mir::mono::CodegenUnit;
18 use crate::query::Key;
20 use crate::traits::query::{
21 CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
22 CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
23 CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
25 use crate::traits::query::{
26 DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
29 use crate::traits::specialization_graph;
30 use crate::traits::{self, ImplSource};
31 use crate::ty::context::TyCtxtFeed;
32 use crate::ty::fast_reject::SimplifiedType;
33 use crate::ty::layout::TyAndLayout;
34 use crate::ty::subst::{GenericArg, SubstsRef};
35 use crate::ty::util::AlwaysRequiresDrop;
36 use crate::ty::GeneratorDiagnosticData;
37 use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
39 use rustc_ast::expand::allocator::AllocatorKind;
40 use rustc_attr as attr;
41 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
42 use rustc_data_structures::steal::Steal;
43 use rustc_data_structures::svh::Svh;
44 use rustc_data_structures::sync::Lrc;
45 use rustc_data_structures::unord::UnordSet;
46 use rustc_errors::ErrorGuaranteed;
48 use rustc_hir::def::DefKind;
49 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
50 use rustc_hir::hir_id::OwnerId;
51 use rustc_hir::lang_items::{LangItem, LanguageItems};
52 use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
53 use rustc_index::vec::IndexVec;
54 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
55 use rustc_session::cstore::{CrateDepKind, CrateSource};
56 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
57 use rustc_session::lint::LintExpectationId;
58 use rustc_session::Limits;
59 use rustc_span::symbol::Symbol;
60 use rustc_span::{Span, DUMMY_SP};
61 use rustc_target::abi;
62 use rustc_target::spec::PanicStrategy;
64 use std::path::PathBuf;
67 pub(crate) use rustc_query_system::query::QueryJobId;
68 use rustc_query_system::query::*;
70 #[derive(Copy, Clone)]
71 pub struct TyCtxtAt<'tcx> {
72 pub tcx: TyCtxt<'tcx>,
76 impl<'tcx> Deref for TyCtxtAt<'tcx> {
77 type Target = TyCtxt<'tcx>;
79 fn deref(&self) -> &Self::Target {
84 #[derive(Copy, Clone)]
85 pub struct TyCtxtEnsure<'tcx> {
86 pub tcx: TyCtxt<'tcx>,
89 impl<'tcx> TyCtxt<'tcx> {
90 /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
91 /// are executed instead of just returning their results.
93 pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
94 TyCtxtEnsure { tcx: self }
97 /// Returns a transparent wrapper for `TyCtxt` which uses
98 /// `span` as the location of queries performed through it.
100 pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
101 TyCtxtAt { tcx: self, span }
104 pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
105 self.queries.try_mark_green(self, dep_node)
109 macro_rules! query_helper_param_ty {
110 (DefId) => { impl IntoQueryParam<DefId> };
111 (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
115 macro_rules! query_if_arena {
116 ([] $arena:ty, $no_arena:ty) => {
119 ([(arena_cache) $($rest:tt)*] $arena:ty, $no_arena:ty) => {
122 ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
123 query_if_arena!([$($modifiers)*]$($args)*)
127 macro_rules! separate_provide_extern_decl {
128 ([][$name:ident]) => {
131 ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
134 query_keys::$name<'tcx>,
135 ) -> query_values::$name<'tcx>
137 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
138 separate_provide_extern_decl!([$($modifiers)*][$($args)*])
142 macro_rules! separate_provide_extern_default {
143 ([][$name:ident]) => {
146 ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
148 "`tcx.{}({:?})` unsupported by its crate; \
149 perhaps the `{}` query was never assigned a provider function",
155 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
156 separate_provide_extern_default!([$($modifiers)*][$($args)*])
160 macro_rules! opt_remap_env_constness {
161 ([][$name:ident]) => {};
162 ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
163 let $name = $name.without_const();
165 ([$other:tt $($modifiers:tt)*][$name:ident]) => {
166 opt_remap_env_constness!([$($modifiers)*][$name])
170 macro_rules! define_callbacks {
173 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
175 // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
176 // below, but using type aliases instead of associated types, to bypass
177 // the limitations around normalizing under HRTB - for example, this:
178 // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
179 // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
180 // This is primarily used by the `provide!` macro in `rustc_metadata`.
181 #[allow(nonstandard_style, unused_lifetimes)]
185 $(pub type $name<'tcx> = $($K)*;)*
187 #[allow(nonstandard_style, unused_lifetimes, unused_parens)]
188 pub mod query_values {
191 $(pub type $name<'tcx> = query_if_arena!([$($modifiers)*] <$V as Deref>::Target, $V);)*
193 #[allow(nonstandard_style, unused_lifetimes, unused_parens)]
194 pub mod query_storage {
198 pub type $name<'tcx> = query_if_arena!([$($modifiers)*]
199 <<$($K)* as Key>::CacheSelector
200 as CacheSelector<'tcx, <$V as Deref>::Target>>::ArenaCache,
201 <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
206 #[allow(nonstandard_style, unused_lifetimes)]
207 pub mod query_stored {
210 $(pub type $name<'tcx> = $V;)*
214 pub struct QueryCaches<'tcx> {
215 $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
218 impl<'tcx> TyCtxtEnsure<'tcx> {
221 pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
222 let key = key.into_query_param();
223 opt_remap_env_constness!([$($modifiers)*][key]);
225 match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
227 None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
232 impl<'tcx> TyCtxt<'tcx> {
236 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
238 self.at(DUMMY_SP).$name(key)
242 impl<'tcx> TyCtxtAt<'tcx> {
245 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
247 let key = key.into_query_param();
248 opt_remap_env_constness!([$($modifiers)*][key]);
250 match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
251 Some(value) => value,
252 None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
257 pub struct Providers {
258 $(pub $name: for<'tcx> fn(
260 query_keys::$name<'tcx>,
261 ) -> query_values::$name<'tcx>,)*
264 pub struct ExternProviders {
265 $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
268 impl Default for Providers {
269 fn default() -> Self {
270 use crate::query::Key;
273 $($name: |_, key| bug!(
274 "`tcx.{}({:?})` is not supported for {} crate;\n
275 hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n
276 If that's not the case, {} was likely never assigned to a provider function.\n",
279 if key.query_crate_is_local() { "local" } else { "external" },
286 impl Default for ExternProviders {
287 fn default() -> Self {
289 $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
294 impl Copy for Providers {}
295 impl Clone for Providers {
296 fn clone(&self) -> Self { *self }
299 impl Copy for ExternProviders {}
300 impl Clone for ExternProviders {
301 fn clone(&self) -> Self { *self }
304 pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
305 fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
307 fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
314 key: query_keys::$name<'tcx>,
321 macro_rules! hash_result {
323 Some(dep_graph::hash_result)
325 ([(no_hash) $($rest:tt)*]) => {{
328 ([$other:tt $($modifiers:tt)*]) => {
329 hash_result!([$($modifiers)*])
333 macro_rules! define_feedable {
334 ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
335 $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
338 pub fn $name(self, value: query_values::$name<'tcx>) -> $V {
339 let key = self.key().into_query_param();
340 opt_remap_env_constness!([$($modifiers)*][key]);
343 let cache = &tcx.query_caches.$name;
345 match try_get_cached(tcx, cache, &key) {
348 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
353 let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
354 let dep_node_index = tcx.dep_graph.with_feed_task(
359 hash_result!([$($modifiers)*]),
361 cache.complete(key, value, dep_node_index)
369 // Each of these queries corresponds to a function pointer field in the
370 // `Providers` struct for requesting a value of that type, and a method
371 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
372 // which memoizes and does dep-graph tracking, wrapping around the actual
373 // `Providers` that the driver creates (using several `rustc_*` crates).
375 // The result type of each query must implement `Clone`, and additionally
376 // `ty::query::values::Value`, which produces an appropriate placeholder
377 // (error) value if the query resulted in a query cycle.
378 // Queries marked with `fatal_cycle` do not need the latter implementation,
379 // as they will raise an fatal error on query cycles instead.
381 rustc_query_append! { define_callbacks! }
382 rustc_feedable_queries! { define_feedable! }
385 use super::{DefId, LocalDefId, OwnerId};
387 /// An analogue of the `Into` trait that's intended only for query parameters.
389 /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
390 /// user call `to_def_id` to convert between them everywhere else.
391 pub trait IntoQueryParam<P> {
392 fn into_query_param(self) -> P;
395 impl<P> IntoQueryParam<P> for P {
397 fn into_query_param(self) -> P {
402 impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
404 fn into_query_param(self) -> P {
409 impl IntoQueryParam<LocalDefId> for OwnerId {
411 fn into_query_param(self) -> LocalDefId {
416 impl IntoQueryParam<DefId> for LocalDefId {
418 fn into_query_param(self) -> DefId {
423 impl IntoQueryParam<DefId> for OwnerId {
425 fn into_query_param(self) -> DefId {
431 use sealed::IntoQueryParam;
433 impl<'tcx> TyCtxt<'tcx> {
434 pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
435 let def_id = def_id.into_query_param();
436 self.opt_def_kind(def_id)
437 .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
440 pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
441 ty::EarlyBinder(self.type_of(def_id))
445 impl<'tcx> TyCtxtAt<'tcx> {
446 pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
447 let def_id = def_id.into_query_param();
448 self.opt_def_kind(def_id)
449 .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
452 pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
453 ty::EarlyBinder(self.type_of(def_id))