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