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