]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/query.rs
Auto merge of #99814 - aliemjay:patch-2, r=jackh726
[rust.git] / compiler / rustc_middle / src / ty / query.rs
1 use crate::dep_graph;
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};
11 use crate::mir;
12 use crate::mir::interpret::GlobalId;
13 use crate::mir::interpret::{
14     ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
15 };
16 use crate::mir::interpret::{LitToConstError, LitToConstInput};
17 use crate::mir::mono::CodegenUnit;
18 use crate::query::Key;
19 use crate::thir;
20 use crate::traits::query::{
21     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
22     CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
23     CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
24 };
25 use crate::traits::query::{
26     DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
27     OutlivesBound,
28 };
29 use crate::traits::specialization_graph;
30 use crate::traits::{self, ImplSource};
31 use crate::ty::fast_reject::SimplifiedType;
32 use crate::ty::layout::TyAndLayout;
33 use crate::ty::subst::{GenericArg, SubstsRef};
34 use crate::ty::util::AlwaysRequiresDrop;
35 use crate::ty::GeneratorDiagnosticData;
36 use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
37 use rustc_ast as ast;
38 use rustc_ast::expand::allocator::AllocatorKind;
39 use rustc_attr as attr;
40 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
41 use rustc_data_structures::steal::Steal;
42 use rustc_data_structures::svh::Svh;
43 use rustc_data_structures::sync::Lrc;
44 use rustc_data_structures::unord::UnordSet;
45 use rustc_errors::ErrorGuaranteed;
46 use rustc_hir as hir;
47 use rustc_hir::def::DefKind;
48 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
49 use rustc_hir::hir_id::OwnerId;
50 use rustc_hir::lang_items::{LangItem, LanguageItems};
51 use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
52 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
53 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
54 use rustc_session::cstore::{CrateDepKind, CrateSource};
55 use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
56 use rustc_session::lint::LintExpectationId;
57 use rustc_session::Limits;
58 use rustc_span::symbol::Symbol;
59 use rustc_span::{Span, DUMMY_SP};
60 use rustc_target::abi;
61 use rustc_target::spec::PanicStrategy;
62 use std::ops::Deref;
63 use std::path::PathBuf;
64 use std::sync::Arc;
65
66 pub(crate) use rustc_query_system::query::QueryJobId;
67 use rustc_query_system::query::*;
68
69 #[derive(Copy, Clone)]
70 pub struct TyCtxtAt<'tcx> {
71     pub tcx: TyCtxt<'tcx>,
72     pub span: Span,
73 }
74
75 impl<'tcx> Deref for TyCtxtAt<'tcx> {
76     type Target = TyCtxt<'tcx>;
77     #[inline(always)]
78     fn deref(&self) -> &Self::Target {
79         &self.tcx
80     }
81 }
82
83 #[derive(Copy, Clone)]
84 pub struct TyCtxtEnsure<'tcx> {
85     pub tcx: TyCtxt<'tcx>,
86 }
87
88 impl<'tcx> TyCtxt<'tcx> {
89     /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
90     /// are executed instead of just returning their results.
91     #[inline(always)]
92     pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
93         TyCtxtEnsure { tcx: self }
94     }
95
96     /// Returns a transparent wrapper for `TyCtxt` which uses
97     /// `span` as the location of queries performed through it.
98     #[inline(always)]
99     pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
100         TyCtxtAt { tcx: self, span }
101     }
102
103     pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
104         self.queries.try_mark_green(self, dep_node)
105     }
106 }
107
108 /// Helper for `TyCtxtEnsure` to avoid a closure.
109 #[inline(always)]
110 fn noop<T>(_: &T) {}
111
112 /// Helper to ensure that queries only return `Copy` types.
113 #[inline(always)]
114 fn copy<T: Copy>(x: &T) -> T {
115     *x
116 }
117
118 macro_rules! query_helper_param_ty {
119     (DefId) => { impl IntoQueryParam<DefId> };
120     ($K:ty) => { $K };
121 }
122
123 macro_rules! query_storage {
124     ([][$K:ty, $V:ty]) => {
125         <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
126     };
127     ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
128         <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
129     };
130     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
131         query_storage!([$($modifiers)*][$($args)*])
132     };
133 }
134
135 macro_rules! separate_provide_extern_decl {
136     ([][$name:ident]) => {
137         ()
138     };
139     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
140         for<'tcx> fn(
141             TyCtxt<'tcx>,
142             query_keys::$name<'tcx>,
143         ) -> query_values::$name<'tcx>
144     };
145     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
146         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
147     };
148 }
149
150 macro_rules! separate_provide_extern_default {
151     ([][$name:ident]) => {
152         ()
153     };
154     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
155         |_, key| bug!(
156             "`tcx.{}({:?})` unsupported by its crate; \
157              perhaps the `{}` query was never assigned a provider function",
158             stringify!($name),
159             key,
160             stringify!($name),
161         )
162     };
163     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
164         separate_provide_extern_default!([$($modifiers)*][$($args)*])
165     };
166 }
167
168 macro_rules! opt_remap_env_constness {
169     ([][$name:ident]) => {};
170     ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
171         let $name = $name.without_const();
172     };
173     ([$other:tt $($modifiers:tt)*][$name:ident]) => {
174         opt_remap_env_constness!([$($modifiers)*][$name])
175     };
176 }
177
178 macro_rules! define_callbacks {
179     (
180      $($(#[$attr:meta])*
181         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
182
183         // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
184         // below, but using type aliases instead of associated types, to bypass
185         // the limitations around normalizing under HRTB - for example, this:
186         // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
187         // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
188         // This is primarily used by the `provide!` macro in `rustc_metadata`.
189         #[allow(nonstandard_style, unused_lifetimes)]
190         pub mod query_keys {
191             use super::*;
192
193             $(pub type $name<'tcx> = $($K)*;)*
194         }
195         #[allow(nonstandard_style, unused_lifetimes)]
196         pub mod query_values {
197             use super::*;
198
199             $(pub type $name<'tcx> = $V;)*
200         }
201         #[allow(nonstandard_style, unused_lifetimes)]
202         pub mod query_storage {
203             use super::*;
204
205             $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
206         }
207         #[allow(nonstandard_style, unused_lifetimes)]
208         pub mod query_stored {
209             use super::*;
210
211             $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
212         }
213
214         #[derive(Default)]
215         pub struct QueryCaches<'tcx> {
216             $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
217         }
218
219         impl<'tcx> TyCtxtEnsure<'tcx> {
220             $($(#[$attr])*
221             #[inline(always)]
222             pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
223                 let key = key.into_query_param();
224                 opt_remap_env_constness!([$($modifiers)*][key]);
225
226                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
227
228                 match cached {
229                     Ok(()) => return,
230                     Err(()) => (),
231                 }
232
233                 self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
234             })*
235         }
236
237         impl<'tcx> TyCtxt<'tcx> {
238             $($(#[$attr])*
239             #[inline(always)]
240             #[must_use]
241             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
242             {
243                 self.at(DUMMY_SP).$name(key)
244             })*
245         }
246
247         impl<'tcx> TyCtxtAt<'tcx> {
248             $($(#[$attr])*
249             #[inline(always)]
250             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
251             {
252                 let key = key.into_query_param();
253                 opt_remap_env_constness!([$($modifiers)*][key]);
254
255                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
256
257                 match cached {
258                     Ok(value) => return value,
259                     Err(()) => (),
260                 }
261
262                 self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
263             })*
264         }
265
266         pub struct Providers {
267             $(pub $name: for<'tcx> fn(
268                 TyCtxt<'tcx>,
269                 query_keys::$name<'tcx>,
270             ) -> query_values::$name<'tcx>,)*
271         }
272
273         pub struct ExternProviders {
274             $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
275         }
276
277         impl Default for Providers {
278             fn default() -> Self {
279                 use crate::query::Key;
280
281                 Providers {
282                     $($name: |_, key| bug!(
283                         "`tcx.{}({:?})` is not supported for {} crate;\n
284                         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
285                         If that's not the case, {} was likely never assigned to a provider function.\n",
286                         stringify!($name),
287                         key,
288                         if key.query_crate_is_local() { "local" } else { "external" },
289                         stringify!($name),
290                     ),)*
291                 }
292             }
293         }
294
295         impl Default for ExternProviders {
296             fn default() -> Self {
297                 ExternProviders {
298                     $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
299                 }
300             }
301         }
302
303         impl Copy for Providers {}
304         impl Clone for Providers {
305             fn clone(&self) -> Self { *self }
306         }
307
308         impl Copy for ExternProviders {}
309         impl Clone for ExternProviders {
310             fn clone(&self) -> Self { *self }
311         }
312
313         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
314             fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
315
316             fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
317
318             $($(#[$attr])*
319             fn $name(
320                 &'tcx self,
321                 tcx: TyCtxt<'tcx>,
322                 span: Span,
323                 key: query_keys::$name<'tcx>,
324                 mode: QueryMode,
325             ) -> Option<query_stored::$name<'tcx>>;)*
326         }
327     };
328 }
329
330 // Each of these queries corresponds to a function pointer field in the
331 // `Providers` struct for requesting a value of that type, and a method
332 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
333 // which memoizes and does dep-graph tracking, wrapping around the actual
334 // `Providers` that the driver creates (using several `rustc_*` crates).
335 //
336 // The result type of each query must implement `Clone`, and additionally
337 // `ty::query::values::Value`, which produces an appropriate placeholder
338 // (error) value if the query resulted in a query cycle.
339 // Queries marked with `fatal_cycle` do not need the latter implementation,
340 // as they will raise an fatal error on query cycles instead.
341
342 rustc_query_append! { define_callbacks! }
343
344 mod sealed {
345     use super::{DefId, LocalDefId, OwnerId};
346
347     /// An analogue of the `Into` trait that's intended only for query parameters.
348     ///
349     /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
350     /// user call `to_def_id` to convert between them everywhere else.
351     pub trait IntoQueryParam<P> {
352         fn into_query_param(self) -> P;
353     }
354
355     impl<P> IntoQueryParam<P> for P {
356         #[inline(always)]
357         fn into_query_param(self) -> P {
358             self
359         }
360     }
361
362     impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
363         #[inline(always)]
364         fn into_query_param(self) -> P {
365             *self
366         }
367     }
368
369     impl IntoQueryParam<DefId> for LocalDefId {
370         #[inline(always)]
371         fn into_query_param(self) -> DefId {
372             self.to_def_id()
373         }
374     }
375
376     impl IntoQueryParam<DefId> for OwnerId {
377         #[inline(always)]
378         fn into_query_param(self) -> DefId {
379             self.to_def_id()
380         }
381     }
382 }
383
384 use sealed::IntoQueryParam;
385
386 impl<'tcx> TyCtxt<'tcx> {
387     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
388         let def_id = def_id.into_query_param();
389         self.opt_def_kind(def_id)
390             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
391     }
392 }
393
394 impl<'tcx> TyCtxtAt<'tcx> {
395     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
396         let def_id = def_id.into_query_param();
397         self.opt_def_kind(def_id)
398             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
399     }
400 }