]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/query.rs
Auto merge of #102596 - scottmcm:option-bool-calloc, r=Mark-Simulacrum
[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::OwnerId;
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.{}({:?})` is not supported for external or local crate;\n
281                         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 (likely the local crate).\n
282                         If that's not the case, {} was likely never assigned to a provider function.\n",
283                         stringify!($name),
284                         key,
285                         stringify!($name),
286                     ),)*
287                 }
288             }
289         }
290
291         impl Default for ExternProviders {
292             fn default() -> Self {
293                 ExternProviders {
294                     $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
295                 }
296             }
297         }
298
299         impl Copy for Providers {}
300         impl Clone for Providers {
301             fn clone(&self) -> Self { *self }
302         }
303
304         impl Copy for ExternProviders {}
305         impl Clone for ExternProviders {
306             fn clone(&self) -> Self { *self }
307         }
308
309         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
310             fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
311
312             fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
313
314             $($(#[$attr])*
315             fn $name(
316                 &'tcx self,
317                 tcx: TyCtxt<'tcx>,
318                 span: Span,
319                 key: query_keys::$name<'tcx>,
320                 mode: QueryMode,
321             ) -> Option<query_stored::$name<'tcx>>;)*
322         }
323     };
324 }
325
326 // Each of these queries corresponds to a function pointer field in the
327 // `Providers` struct for requesting a value of that type, and a method
328 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
329 // which memoizes and does dep-graph tracking, wrapping around the actual
330 // `Providers` that the driver creates (using several `rustc_*` crates).
331 //
332 // The result type of each query must implement `Clone`, and additionally
333 // `ty::query::values::Value`, which produces an appropriate placeholder
334 // (error) value if the query resulted in a query cycle.
335 // Queries marked with `fatal_cycle` do not need the latter implementation,
336 // as they will raise an fatal error on query cycles instead.
337
338 rustc_query_append! { define_callbacks! }
339
340 mod sealed {
341     use super::{DefId, LocalDefId, OwnerId};
342
343     /// An analogue of the `Into` trait that's intended only for query parameters.
344     ///
345     /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
346     /// user call `to_def_id` to convert between them everywhere else.
347     pub trait IntoQueryParam<P> {
348         fn into_query_param(self) -> P;
349     }
350
351     impl<P> IntoQueryParam<P> for P {
352         #[inline(always)]
353         fn into_query_param(self) -> P {
354             self
355         }
356     }
357
358     impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
359         #[inline(always)]
360         fn into_query_param(self) -> P {
361             *self
362         }
363     }
364
365     impl IntoQueryParam<DefId> for LocalDefId {
366         #[inline(always)]
367         fn into_query_param(self) -> DefId {
368             self.to_def_id()
369         }
370     }
371
372     impl IntoQueryParam<DefId> for OwnerId {
373         #[inline(always)]
374         fn into_query_param(self) -> DefId {
375             self.to_def_id()
376         }
377     }
378 }
379
380 use sealed::IntoQueryParam;
381
382 impl<'tcx> TyCtxt<'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 }
389
390 impl<'tcx> TyCtxtAt<'tcx> {
391     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
392         let def_id = def_id.into_query_param();
393         self.opt_def_kind(def_id)
394             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
395     }
396 }