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