]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/query.rs
Rollup merge of #107321 - lcnr:comment, r=compiler-errors
[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 /// Helper for `TyCtxtEnsure` to avoid a closure.
110 #[inline(always)]
111 fn noop<T>(_: &T) {}
112
113 /// Helper to ensure that queries only return `Copy` types.
114 #[inline(always)]
115 fn copy<T: Copy>(x: &T) -> T {
116     *x
117 }
118
119 macro_rules! query_helper_param_ty {
120     (DefId) => { impl IntoQueryParam<DefId> };
121     ($K:ty) => { $K };
122 }
123
124 macro_rules! query_storage {
125     ([][$K:ty, $V:ty]) => {
126         <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
127     };
128     ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
129         <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
130     };
131     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
132         query_storage!([$($modifiers)*][$($args)*])
133     };
134 }
135
136 macro_rules! separate_provide_extern_decl {
137     ([][$name:ident]) => {
138         ()
139     };
140     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
141         for<'tcx> fn(
142             TyCtxt<'tcx>,
143             query_keys::$name<'tcx>,
144         ) -> query_values::$name<'tcx>
145     };
146     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
147         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
148     };
149 }
150
151 macro_rules! separate_provide_extern_default {
152     ([][$name:ident]) => {
153         ()
154     };
155     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
156         |_, key| bug!(
157             "`tcx.{}({:?})` unsupported by its crate; \
158              perhaps the `{}` query was never assigned a provider function",
159             stringify!($name),
160             key,
161             stringify!($name),
162         )
163     };
164     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
165         separate_provide_extern_default!([$($modifiers)*][$($args)*])
166     };
167 }
168
169 macro_rules! opt_remap_env_constness {
170     ([][$name:ident]) => {};
171     ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
172         let $name = $name.without_const();
173     };
174     ([$other:tt $($modifiers:tt)*][$name:ident]) => {
175         opt_remap_env_constness!([$($modifiers)*][$name])
176     };
177 }
178
179 macro_rules! define_callbacks {
180     (
181      $($(#[$attr:meta])*
182         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
183
184         // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
185         // below, but using type aliases instead of associated types, to bypass
186         // the limitations around normalizing under HRTB - for example, this:
187         // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
188         // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
189         // This is primarily used by the `provide!` macro in `rustc_metadata`.
190         #[allow(nonstandard_style, unused_lifetimes)]
191         pub mod query_keys {
192             use super::*;
193
194             $(pub type $name<'tcx> = $($K)*;)*
195         }
196         #[allow(nonstandard_style, unused_lifetimes)]
197         pub mod query_values {
198             use super::*;
199
200             $(pub type $name<'tcx> = $V;)*
201         }
202         #[allow(nonstandard_style, unused_lifetimes)]
203         pub mod query_storage {
204             use super::*;
205
206             $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
207         }
208         #[allow(nonstandard_style, unused_lifetimes)]
209         pub mod query_stored {
210             use super::*;
211
212             $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
213         }
214
215         #[derive(Default)]
216         pub struct QueryCaches<'tcx> {
217             $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
218         }
219
220         impl<'tcx> TyCtxtEnsure<'tcx> {
221             $($(#[$attr])*
222             #[inline(always)]
223             pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
224                 let key = key.into_query_param();
225                 opt_remap_env_constness!([$($modifiers)*][key]);
226
227                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
228
229                 match cached {
230                     Ok(()) => return,
231                     Err(()) => (),
232                 }
233
234                 self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
235             })*
236         }
237
238         impl<'tcx> TyCtxt<'tcx> {
239             $($(#[$attr])*
240             #[inline(always)]
241             #[must_use]
242             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
243             {
244                 self.at(DUMMY_SP).$name(key)
245             })*
246         }
247
248         impl<'tcx> TyCtxtAt<'tcx> {
249             $($(#[$attr])*
250             #[inline(always)]
251             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
252             {
253                 let key = key.into_query_param();
254                 opt_remap_env_constness!([$($modifiers)*][key]);
255
256                 let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
257
258                 match cached {
259                     Ok(value) => return value,
260                     Err(()) => (),
261                 }
262
263                 self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
264             })*
265         }
266
267         pub struct Providers {
268             $(pub $name: for<'tcx> fn(
269                 TyCtxt<'tcx>,
270                 query_keys::$name<'tcx>,
271             ) -> query_values::$name<'tcx>,)*
272         }
273
274         pub struct ExternProviders {
275             $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
276         }
277
278         impl Default for Providers {
279             fn default() -> Self {
280                 use crate::query::Key;
281
282                 Providers {
283                     $($name: |_, key| bug!(
284                         "`tcx.{}({:?})` is not supported for {} crate;\n
285                         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
286                         If that's not the case, {} was likely never assigned to a provider function.\n",
287                         stringify!($name),
288                         key,
289                         if key.query_crate_is_local() { "local" } else { "external" },
290                         stringify!($name),
291                     ),)*
292                 }
293             }
294         }
295
296         impl Default for ExternProviders {
297             fn default() -> Self {
298                 ExternProviders {
299                     $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
300                 }
301             }
302         }
303
304         impl Copy for Providers {}
305         impl Clone for Providers {
306             fn clone(&self) -> Self { *self }
307         }
308
309         impl Copy for ExternProviders {}
310         impl Clone for ExternProviders {
311             fn clone(&self) -> Self { *self }
312         }
313
314         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
315             fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
316
317             fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
318
319             $($(#[$attr])*
320             fn $name(
321                 &'tcx self,
322                 tcx: TyCtxt<'tcx>,
323                 span: Span,
324                 key: query_keys::$name<'tcx>,
325                 mode: QueryMode,
326             ) -> Option<query_stored::$name<'tcx>>;)*
327         }
328     };
329 }
330
331 macro_rules! hash_result {
332     ([]) => {{
333         Some(dep_graph::hash_result)
334     }};
335     ([(no_hash) $($rest:tt)*]) => {{
336         None
337     }};
338     ([$other:tt $($modifiers:tt)*]) => {
339         hash_result!([$($modifiers)*])
340     };
341 }
342
343 macro_rules! define_feedable {
344     ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
345         $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
346             $(#[$attr])*
347             #[inline(always)]
348             pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
349                 let key = self.key().into_query_param();
350                 opt_remap_env_constness!([$($modifiers)*][key]);
351
352                 let tcx = self.tcx;
353                 let cache = &tcx.query_caches.$name;
354
355                 let cached = try_get_cached(tcx, cache, &key, copy);
356
357                 match cached {
358                     Ok(old) => {
359                         bug!(
360                             "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
361                             stringify!($name),
362                         );
363                     }
364                     Err(()) => (),
365                 }
366
367                 let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
368                 let dep_node_index = tcx.dep_graph.with_feed_task(
369                     dep_node,
370                     tcx,
371                     key,
372                     &value,
373                     hash_result!([$($modifiers)*]),
374                 );
375                 cache.complete(key, value, dep_node_index)
376             }
377         })*
378     }
379 }
380
381 // Each of these queries corresponds to a function pointer field in the
382 // `Providers` struct for requesting a value of that type, and a method
383 // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
384 // which memoizes and does dep-graph tracking, wrapping around the actual
385 // `Providers` that the driver creates (using several `rustc_*` crates).
386 //
387 // The result type of each query must implement `Clone`, and additionally
388 // `ty::query::values::Value`, which produces an appropriate placeholder
389 // (error) value if the query resulted in a query cycle.
390 // Queries marked with `fatal_cycle` do not need the latter implementation,
391 // as they will raise an fatal error on query cycles instead.
392
393 rustc_query_append! { define_callbacks! }
394 rustc_feedable_queries! { define_feedable! }
395
396 mod sealed {
397     use super::{DefId, LocalDefId, OwnerId};
398
399     /// An analogue of the `Into` trait that's intended only for query parameters.
400     ///
401     /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
402     /// user call `to_def_id` to convert between them everywhere else.
403     pub trait IntoQueryParam<P> {
404         fn into_query_param(self) -> P;
405     }
406
407     impl<P> IntoQueryParam<P> for P {
408         #[inline(always)]
409         fn into_query_param(self) -> P {
410             self
411         }
412     }
413
414     impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
415         #[inline(always)]
416         fn into_query_param(self) -> P {
417             *self
418         }
419     }
420
421     impl IntoQueryParam<DefId> for LocalDefId {
422         #[inline(always)]
423         fn into_query_param(self) -> DefId {
424             self.to_def_id()
425         }
426     }
427
428     impl IntoQueryParam<DefId> for OwnerId {
429         #[inline(always)]
430         fn into_query_param(self) -> DefId {
431             self.to_def_id()
432         }
433     }
434 }
435
436 use sealed::IntoQueryParam;
437
438 impl<'tcx> TyCtxt<'tcx> {
439     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
440         let def_id = def_id.into_query_param();
441         self.opt_def_kind(def_id)
442             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
443     }
444
445     pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
446         ty::EarlyBinder(self.type_of(def_id))
447     }
448 }
449
450 impl<'tcx> TyCtxtAt<'tcx> {
451     pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
452         let def_id = def_id.into_query_param();
453         self.opt_def_kind(def_id)
454             .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
455     }
456
457     pub fn bound_type_of(self, def_id: impl IntoQueryParam<DefId>) -> ty::EarlyBinder<Ty<'tcx>> {
458         ty::EarlyBinder(self.type_of(def_id))
459     }
460 }