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};
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::{bit_set::FiniteBitSet, 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 /// Helper for `TyCtxtEnsure` to avoid a closure.
113 /// Helper to ensure that queries only return `Copy` types.
115 fn copy<T: Copy>(x: &T) -> T {
119 macro_rules! query_helper_param_ty {
120 (DefId) => { impl IntoQueryParam<DefId> };
124 macro_rules! query_storage {
125 ([][$K:ty, $V:ty]) => {
126 <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
128 ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
129 <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
131 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
132 query_storage!([$($modifiers)*][$($args)*])
136 macro_rules! separate_provide_extern_decl {
137 ([][$name:ident]) => {
140 ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
143 query_keys::$name<'tcx>,
144 ) -> query_values::$name<'tcx>
146 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
147 separate_provide_extern_decl!([$($modifiers)*][$($args)*])
151 macro_rules! separate_provide_extern_default {
152 ([][$name:ident]) => {
155 ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
157 "`tcx.{}({:?})` unsupported by its crate; \
158 perhaps the `{}` query was never assigned a provider function",
164 ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
165 separate_provide_extern_default!([$($modifiers)*][$($args)*])
169 macro_rules! opt_remap_env_constness {
170 ([][$name:ident]) => {};
171 ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
172 let $name = $name.without_const();
174 ([$other:tt $($modifiers:tt)*][$name:ident]) => {
175 opt_remap_env_constness!([$($modifiers)*][$name])
179 macro_rules! define_callbacks {
182 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
184 // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
185 // below, but using type aliases instead of associated types, to bypass
186 // the limitations around normalizing under HRTB - for example, this:
187 // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
188 // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
189 // This is primarily used by the `provide!` macro in `rustc_metadata`.
190 #[allow(nonstandard_style, unused_lifetimes)]
194 $(pub type $name<'tcx> = $($K)*;)*
196 #[allow(nonstandard_style, unused_lifetimes)]
197 pub mod query_values {
200 $(pub type $name<'tcx> = $V;)*
202 #[allow(nonstandard_style, unused_lifetimes)]
203 pub mod query_storage {
206 $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
208 #[allow(nonstandard_style, unused_lifetimes)]
209 pub mod query_stored {
212 $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
216 pub struct QueryCaches<'tcx> {
217 $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
220 impl<'tcx> TyCtxtEnsure<'tcx> {
223 pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
224 let key = key.into_query_param();
225 opt_remap_env_constness!([$($modifiers)*][key]);
227 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
234 self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
238 impl<'tcx> TyCtxt<'tcx> {
242 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
244 self.at(DUMMY_SP).$name(key)
248 impl<'tcx> TyCtxtAt<'tcx> {
251 pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
253 let key = key.into_query_param();
254 opt_remap_env_constness!([$($modifiers)*][key]);
256 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
259 Ok(value) => return value,
263 self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
267 pub struct Providers {
268 $(pub $name: for<'tcx> fn(
270 query_keys::$name<'tcx>,
271 ) -> query_values::$name<'tcx>,)*
274 pub struct ExternProviders {
275 $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
278 impl Default for Providers {
279 fn default() -> Self {
280 use crate::query::Key;
283 $($name: |_, key| bug!(
284 "`tcx.{}({:?})` is not supported for {} crate;\n
285 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
286 If that's not the case, {} was likely never assigned to a provider function.\n",
289 if key.query_crate_is_local() { "local" } else { "external" },
296 impl Default for ExternProviders {
297 fn default() -> Self {
299 $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
304 impl Copy for Providers {}
305 impl Clone for Providers {
306 fn clone(&self) -> Self { *self }
309 impl Copy for ExternProviders {}
310 impl Clone for ExternProviders {
311 fn clone(&self) -> Self { *self }
314 pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
315 fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
317 fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
324 key: query_keys::$name<'tcx>,
326 ) -> Option<query_stored::$name<'tcx>>;)*
331 macro_rules! hash_result {
333 Some(dep_graph::hash_result)
335 ([(no_hash) $($rest:tt)*]) => {{
338 ([$other:tt $($modifiers:tt)*]) => {
339 hash_result!([$($modifiers)*])
343 macro_rules! define_feedable {
344 ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
345 $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
348 pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
349 let key = self.key().into_query_param();
350 opt_remap_env_constness!([$($modifiers)*][key]);
353 let cache = &tcx.query_caches.$name;
355 let cached = try_get_cached(tcx, cache, &key, copy);
360 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
367 let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
368 let dep_node_index = tcx.dep_graph.with_feed_task(
373 hash_result!([$($modifiers)*]),
375 cache.complete(key, value, dep_node_index)
381 // Each of these queries corresponds to a function pointer field in the
382 // `Providers` struct for requesting a value of that type, and a method
383 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
384 // which memoizes and does dep-graph tracking, wrapping around the actual
385 // `Providers` that the driver creates (using several `rustc_*` crates).
387 // The result type of each query must implement `Clone`, and additionally
388 // `ty::query::values::Value`, which produces an appropriate placeholder
389 // (error) value if the query resulted in a query cycle.
390 // Queries marked with `fatal_cycle` do not need the latter implementation,
391 // as they will raise an fatal error on query cycles instead.
393 rustc_query_append! { define_callbacks! }
394 rustc_feedable_queries! { define_feedable! }
397 use super::{DefId, LocalDefId, OwnerId};
399 /// An analogue of the `Into` trait that's intended only for query parameters.
401 /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
402 /// user call `to_def_id` to convert between them everywhere else.
403 pub trait IntoQueryParam<P> {
404 fn into_query_param(self) -> P;
407 impl<P> IntoQueryParam<P> for P {
409 fn into_query_param(self) -> P {
414 impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
416 fn into_query_param(self) -> P {
421 impl IntoQueryParam<DefId> for LocalDefId {
423 fn into_query_param(self) -> DefId {
428 impl IntoQueryParam<DefId> for OwnerId {
430 fn into_query_param(self) -> DefId {
436 use sealed::IntoQueryParam;
438 impl<'tcx> TyCtxt<'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))
446 impl<'tcx> TyCtxtAt<'tcx> {
447 pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
448 let def_id = def_id.into_query_param();
449 self.opt_def_kind(def_id)
450 .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))