]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/query/mod.rs
Make allocator_kind a query.
[rust.git] / compiler / rustc_middle / src / ty / query / mod.rs
1 use crate::dep_graph;
2 use crate::hir::exports::Export;
3 use crate::infer::canonical::{self, Canonical};
4 use crate::lint::LintLevelMap;
5 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
6 use crate::middle::cstore::{CrateDepKind, CrateSource};
7 use crate::middle::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
8 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
9 use crate::middle::lib_features::LibFeatures;
10 use crate::middle::privacy::AccessLevels;
11 use crate::middle::region;
12 use crate::middle::resolve_lifetime::{
13     LifetimeScopeForPath, ObjectLifetimeDefault, Region, ResolveLifetimes,
14 };
15 use crate::middle::stability::{self, DeprecationEntry};
16 use crate::mir;
17 use crate::mir::interpret::GlobalId;
18 use crate::mir::interpret::{ConstAlloc, LitToConstError, LitToConstInput};
19 use crate::mir::interpret::{ConstValue, EvalToAllocationRawResult, EvalToConstValueResult};
20 use crate::mir::mono::CodegenUnit;
21 use crate::thir;
22 use crate::traits::query::{
23     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
24     CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
25     CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
26 };
27 use crate::traits::query::{
28     DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult,
29     OutlivesBound,
30 };
31 use crate::traits::specialization_graph;
32 use crate::traits::{self, ImplSource};
33 use crate::ty::subst::{GenericArg, SubstsRef};
34 use crate::ty::util::AlwaysRequiresDrop;
35 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
36 use rustc_ast::expand::allocator::AllocatorKind;
37 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
38 use rustc_data_structures::steal::Steal;
39 use rustc_data_structures::svh::Svh;
40 use rustc_data_structures::sync::Lrc;
41 use rustc_errors::{ErrorReported, Handler};
42 use rustc_hir as hir;
43 use rustc_hir::def::DefKind;
44 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
45 use rustc_hir::lang_items::{LangItem, LanguageItems};
46 use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
47 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
48 use rustc_serialize::opaque;
49 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
50 use rustc_session::utils::NativeLibKind;
51 use rustc_session::CrateDisambiguator;
52 use rustc_target::spec::PanicStrategy;
53
54 use rustc_ast as ast;
55 use rustc_attr as attr;
56 use rustc_span::symbol::Symbol;
57 use rustc_span::{Span, DUMMY_SP};
58 use std::collections::BTreeMap;
59 use std::ops::Deref;
60 use std::path::PathBuf;
61 use std::sync::Arc;
62
63 pub(crate) use rustc_query_system::query::QueryJobId;
64 use rustc_query_system::query::*;
65
66 pub mod on_disk_cache;
67 pub use self::on_disk_cache::OnDiskCache;
68
69 #[derive(Copy, Clone)]
70 pub struct TyCtxtAt<'tcx> {
71     pub tcx: TyCtxt<'tcx>,
72     pub span: Span,
73 }
74
75 impl 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 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 macro_rules! query_helper_param_ty {
109     (DefId) => { impl IntoQueryParam<DefId> };
110     ($K:ty) => { $K };
111 }
112
113 macro_rules! query_storage {
114     ([][$K:ty, $V:ty]) => {
115         <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache
116     };
117     ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => {
118         <$ty as CacheSelector<$K, $V>>::Cache
119     };
120     ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => {
121         query_storage!([$($($modifiers)*)*][$($args)*])
122     };
123 }
124
125 macro_rules! define_callbacks {
126     (<$tcx:tt>
127      $($(#[$attr:meta])*
128         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
129
130         // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
131         // below, but using type aliases instead of associated types, to bypass
132         // the limitations around normalizing under HRTB - for example, this:
133         // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
134         // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
135         // This is primarily used by the `provide!` macro in `rustc_metadata`.
136         #[allow(nonstandard_style, unused_lifetimes)]
137         pub mod query_keys {
138             use super::*;
139
140             $(pub type $name<$tcx> = $($K)*;)*
141         }
142         #[allow(nonstandard_style, unused_lifetimes)]
143         pub mod query_values {
144             use super::*;
145
146             $(pub type $name<$tcx> = $V;)*
147         }
148         #[allow(nonstandard_style, unused_lifetimes)]
149         pub mod query_storage {
150             use super::*;
151
152             $(pub type $name<$tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
153         }
154         #[allow(nonstandard_style, unused_lifetimes)]
155         pub mod query_stored {
156             use super::*;
157
158             $(pub type $name<$tcx> = <query_storage::$name<$tcx> as QueryStorage>::Stored;)*
159         }
160
161         #[derive(Default)]
162         pub struct QueryCaches<$tcx> {
163             $($(#[$attr])* pub $name: QueryCacheStore<query_storage::$name<$tcx>>,)*
164         }
165
166         impl TyCtxtEnsure<$tcx> {
167             $($(#[$attr])*
168             #[inline(always)]
169             pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
170                 let key = key.into_query_param();
171                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});
172
173                 let lookup = match cached {
174                     Ok(()) => return,
175                     Err(lookup) => lookup,
176                 };
177
178                 self.tcx.queries.$name(self.tcx, DUMMY_SP, key, lookup, QueryMode::Ensure);
179             })*
180         }
181
182         impl TyCtxt<$tcx> {
183             $($(#[$attr])*
184             #[inline(always)]
185             #[must_use]
186             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
187             {
188                 self.at(DUMMY_SP).$name(key)
189             })*
190         }
191
192         impl TyCtxtAt<$tcx> {
193             $($(#[$attr])*
194             #[inline(always)]
195             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
196             {
197                 let key = key.into_query_param();
198                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
199                     value.clone()
200                 });
201
202                 let lookup = match cached {
203                     Ok(value) => return value,
204                     Err(lookup) => lookup,
205                 };
206
207                 self.tcx.queries.$name(self.tcx, self.span, key, lookup, QueryMode::Get).unwrap()
208             })*
209         }
210
211         pub struct Providers {
212             $(pub $name: for<'tcx> fn(
213                 TyCtxt<'tcx>,
214                 query_keys::$name<'tcx>,
215             ) -> query_values::$name<'tcx>,)*
216         }
217
218         impl Default for Providers {
219             fn default() -> Self {
220                 Providers {
221                     $($name: |_, key| bug!(
222                         "`tcx.{}({:?})` unsupported by its crate; \
223                          perhaps the `{}` query was never assigned a provider function",
224                         stringify!($name),
225                         key,
226                         stringify!($name),
227                     ),)*
228                 }
229             }
230         }
231
232         impl Copy for Providers {}
233         impl Clone for Providers {
234             fn clone(&self) -> Self { *self }
235         }
236
237         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
238             #[cfg(parallel_compiler)]
239             unsafe fn deadlock(&'tcx self, tcx: TyCtxt<'tcx>, registry: &rustc_rayon_core::Registry);
240
241             fn encode_query_results(
242                 &'tcx self,
243                 tcx: TyCtxt<'tcx>,
244                 encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
245                 query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
246             ) -> opaque::FileEncodeResult;
247
248             fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>);
249
250             fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
251
252             fn try_print_query_stack(
253                 &'tcx self,
254                 tcx: TyCtxt<'tcx>,
255                 query: Option<QueryJobId<dep_graph::DepKind>>,
256                 handler: &Handler,
257                 num_frames: Option<usize>,
258             ) -> usize;
259
260             $($(#[$attr])*
261             fn $name(
262                 &'tcx self,
263                 tcx: TyCtxt<$tcx>,
264                 span: Span,
265                 key: query_keys::$name<$tcx>,
266                 lookup: QueryLookup,
267                 mode: QueryMode,
268             ) -> Option<query_stored::$name<$tcx>>;)*
269         }
270     };
271 }
272
273 // Each of these queries corresponds to a function pointer field in the
274 // `Providers` struct for requesting a value of that type, and a method
275 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
276 // which memoizes and does dep-graph tracking, wrapping around the actual
277 // `Providers` that the driver creates (using several `rustc_*` crates).
278 //
279 // The result type of each query must implement `Clone`, and additionally
280 // `ty::query::values::Value`, which produces an appropriate placeholder
281 // (error) value if the query resulted in a query cycle.
282 // Queries marked with `fatal_cycle` do not need the latter implementation,
283 // as they will raise an fatal error on query cycles instead.
284
285 rustc_query_append! { [define_callbacks!][<'tcx>] }
286
287 mod sealed {
288     use super::{DefId, LocalDefId};
289
290     /// An analogue of the `Into` trait that's intended only for query paramaters.
291     ///
292     /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
293     /// user call `to_def_id` to convert between them everywhere else.
294     pub trait IntoQueryParam<P> {
295         fn into_query_param(self) -> P;
296     }
297
298     impl<P> IntoQueryParam<P> for P {
299         #[inline(always)]
300         fn into_query_param(self) -> P {
301             self
302         }
303     }
304
305     impl IntoQueryParam<DefId> for LocalDefId {
306         #[inline(always)]
307         fn into_query_param(self) -> DefId {
308             self.to_def_id()
309         }
310     }
311 }
312
313 use sealed::IntoQueryParam;
314
315 impl TyCtxt<'tcx> {
316     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
317         let def_id = def_id.into_query_param();
318         self.opt_def_kind(def_id)
319             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
320     }
321 }
322
323 impl TyCtxtAt<'tcx> {
324     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
325         let def_id = def_id.into_query_param();
326         self.opt_def_kind(def_id)
327             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
328     }
329 }