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