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