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_storage {
116 ([][$K:ty, $V:ty]) => {
117 <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
119 ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
120 <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
122 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
123 query_storage!([$($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)]
188 pub mod query_values {
191 $(pub type $name<'tcx> = $V;)*
193 #[allow(nonstandard_style, unused_lifetimes)]
194 pub mod query_storage {
197 $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
199 #[allow(nonstandard_style, unused_lifetimes)]
200 pub mod query_stored {
203 $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
207 pub struct QueryCaches<'tcx> {
208 $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
211 impl<'tcx> TyCtxtEnsure<'tcx> {
214 pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
215 let key = key.into_query_param();
216 opt_remap_env_constness!([$($modifiers)*][key]);
218 match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
220 None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
225 impl<'tcx> TyCtxt<'tcx> {
229 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
231 self.at(DUMMY_SP).$name(key)
235 impl<'tcx> TyCtxtAt<'tcx> {
238 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
240 let key = key.into_query_param();
241 opt_remap_env_constness!([$($modifiers)*][key]);
243 match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
244 Some(value) => value,
245 None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
250 pub struct Providers {
251 $(pub $name: for<'tcx> fn(
253 query_keys::$name<'tcx>,
254 ) -> query_values::$name<'tcx>,)*
257 pub struct ExternProviders {
258 $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
261 impl Default for Providers {
262 fn default() -> Self {
263 use crate::query::Key;
266 $($name: |_, key| bug!(
267 "`tcx.{}({:?})` is not supported for {} crate;\n
268 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
269 If that's not the case, {} was likely never assigned to a provider function.\n",
272 if key.query_crate_is_local() { "local" } else { "external" },
279 impl Default for ExternProviders {
280 fn default() -> Self {
282 $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
287 impl Copy for Providers {}
288 impl Clone for Providers {
289 fn clone(&self) -> Self { *self }
292 impl Copy for ExternProviders {}
293 impl Clone for ExternProviders {
294 fn clone(&self) -> Self { *self }
297 pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
298 fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
300 fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
307 key: query_keys::$name<'tcx>,
309 ) -> Option<query_stored::$name<'tcx>>;)*
314 macro_rules! hash_result {
316 Some(dep_graph::hash_result)
318 ([(no_hash) $($rest:tt)*]) => {{
321 ([$other:tt $($modifiers:tt)*]) => {
322 hash_result!([$($modifiers)*])
326 macro_rules! define_feedable {
327 ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
328 $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
331 pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
332 let key = self.key().into_query_param();
333 opt_remap_env_constness!([$($modifiers)*][key]);
336 let cache = &tcx.query_caches.$name;
338 match try_get_cached(tcx, cache, &key) {
341 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
346 let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
347 let dep_node_index = tcx.dep_graph.with_feed_task(
352 hash_result!([$($modifiers)*]),
354 cache.complete(key, value, dep_node_index)
362 // Each of these queries corresponds to a function pointer field in the
363 // `Providers` struct for requesting a value of that type, and a method
364 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
365 // which memoizes and does dep-graph tracking, wrapping around the actual
366 // `Providers` that the driver creates (using several `rustc_*` crates).
368 // The result type of each query must implement `Clone`, and additionally
369 // `ty::query::values::Value`, which produces an appropriate placeholder
370 // (error) value if the query resulted in a query cycle.
371 // Queries marked with `fatal_cycle` do not need the latter implementation,
372 // as they will raise an fatal error on query cycles instead.
374 rustc_query_append! { define_callbacks! }
375 rustc_feedable_queries! { define_feedable! }
378 use super::{DefId, LocalDefId, OwnerId};
380 /// An analogue of the `Into` trait that's intended only for query parameters.
382 /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
383 /// user call `to_def_id` to convert between them everywhere else.
384 pub trait IntoQueryParam<P> {
385 fn into_query_param(self) -> P;
388 impl<P> IntoQueryParam<P> for P {
390 fn into_query_param(self) -> P {
395 impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
397 fn into_query_param(self) -> P {
402 impl IntoQueryParam<LocalDefId> for OwnerId {
404 fn into_query_param(self) -> LocalDefId {
409 impl IntoQueryParam<DefId> for LocalDefId {
411 fn into_query_param(self) -> DefId {
416 impl IntoQueryParam<DefId> for OwnerId {
418 fn into_query_param(self) -> DefId {
424 use sealed::IntoQueryParam;
426 impl<'tcx> TyCtxt<'tcx> {
427 pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
428 let def_id = def_id.into_query_param();
429 self.opt_def_kind(def_id)
430 .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
433 pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
434 ty::EarlyBinder(self.type_of(def_id))
438 impl<'tcx> TyCtxtAt<'tcx> {
439 pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
440 let def_id = def_id.into_query_param();
441 self.opt_def_kind(def_id)
442 .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
445 pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
446 ty::EarlyBinder(self.type_of(def_id))