]>
Commit | Line | Data |
---|---|---|
ba9703b0 XL |
1 | //! The implementation of the query system itself. This defines the macros that |
2 | //! generate the actual methods on tcx which find and execute the provider, | |
3 | //! manage the caches, and so forth. | |
4 | ||
5 | use crate::dep_graph::DepGraph; | |
6 | use crate::ty::query::Query; | |
7 | use crate::ty::tls::{self, ImplicitCtxt}; | |
8 | use crate::ty::{self, TyCtxt}; | |
9 | use rustc_query_system::query::QueryContext; | |
10 | use rustc_query_system::query::{CycleError, QueryJobId, QueryJobInfo}; | |
11 | ||
12 | use rustc_data_structures::fx::FxHashMap; | |
13 | use rustc_data_structures::sync::Lock; | |
14 | use rustc_data_structures::thin_vec::ThinVec; | |
15 | use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; | |
16 | use rustc_span::def_id::DefId; | |
17 | use rustc_span::Span; | |
18 | ||
19 | impl QueryContext for TyCtxt<'tcx> { | |
20 | type Query = Query<'tcx>; | |
21 | ||
22 | fn incremental_verify_ich(&self) -> bool { | |
23 | self.sess.opts.debugging_opts.incremental_verify_ich | |
24 | } | |
25 | fn verbose(&self) -> bool { | |
26 | self.sess.verbose() | |
27 | } | |
28 | ||
29 | fn def_path_str(&self, def_id: DefId) -> String { | |
30 | TyCtxt::def_path_str(*self, def_id) | |
31 | } | |
32 | ||
33 | fn dep_graph(&self) -> &DepGraph { | |
34 | &self.dep_graph | |
35 | } | |
36 | ||
37 | fn current_query_job(&self) -> Option<QueryJobId<Self::DepKind>> { | |
38 | tls::with_related_context(*self, |icx| icx.query) | |
39 | } | |
40 | ||
41 | fn try_collect_active_jobs( | |
42 | &self, | |
29967ef6 XL |
43 | ) -> Option<FxHashMap<QueryJobId<Self::DepKind>, QueryJobInfo<Self::DepKind, Self::Query>>> |
44 | { | |
ba9703b0 XL |
45 | self.queries.try_collect_active_jobs() |
46 | } | |
47 | ||
48 | /// Executes a job by changing the `ImplicitCtxt` to point to the | |
49 | /// new query job while it executes. It returns the diagnostics | |
50 | /// captured during execution and the actual result. | |
51 | #[inline(always)] | |
52 | fn start_query<R>( | |
53 | &self, | |
54 | token: QueryJobId<Self::DepKind>, | |
55 | diagnostics: Option<&Lock<ThinVec<Diagnostic>>>, | |
56 | compute: impl FnOnce(Self) -> R, | |
57 | ) -> R { | |
58 | // The `TyCtxt` stored in TLS has the same global interner lifetime | |
59 | // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes | |
60 | // when accessing the `ImplicitCtxt`. | |
61 | tls::with_related_context(*self, move |current_icx| { | |
62 | // Update the `ImplicitCtxt` to point to our new query job. | |
63 | let new_icx = ImplicitCtxt { | |
64 | tcx: *self, | |
65 | query: Some(token), | |
66 | diagnostics, | |
67 | layout_depth: current_icx.layout_depth, | |
68 | task_deps: current_icx.task_deps, | |
69 | }; | |
70 | ||
71 | // Use the `ImplicitCtxt` while we execute the query. | |
f9f354fc XL |
72 | tls::enter_context(&new_icx, |_| { |
73 | rustc_data_structures::stack::ensure_sufficient_stack(|| compute(*self)) | |
74 | }) | |
ba9703b0 XL |
75 | }) |
76 | } | |
77 | } | |
78 | ||
79 | impl<'tcx> TyCtxt<'tcx> { | |
80 | #[inline(never)] | |
81 | #[cold] | |
82 | pub(super) fn report_cycle( | |
83 | self, | |
84 | CycleError { usage, cycle: stack }: CycleError<Query<'tcx>>, | |
85 | ) -> DiagnosticBuilder<'tcx> { | |
86 | assert!(!stack.is_empty()); | |
87 | ||
88 | let fix_span = |span: Span, query: &Query<'tcx>| { | |
89 | self.sess.source_map().guess_head_span(query.default_span(self, span)) | |
90 | }; | |
91 | ||
92 | // Disable naming impls with types in this path, since that | |
93 | // sometimes cycles itself, leading to extra cycle errors. | |
94 | // (And cycle errors around impls tend to occur during the | |
95 | // collect/coherence phases anyhow.) | |
96 | ty::print::with_forced_impl_filename_line(|| { | |
97 | let span = fix_span(stack[1 % stack.len()].span, &stack[0].query); | |
98 | let mut err = struct_span_err!( | |
99 | self.sess, | |
100 | span, | |
101 | E0391, | |
102 | "cycle detected when {}", | |
103 | stack[0].query.describe(self) | |
104 | ); | |
105 | ||
106 | for i in 1..stack.len() { | |
107 | let query = &stack[i].query; | |
108 | let span = fix_span(stack[(i + 1) % stack.len()].span, query); | |
109 | err.span_note(span, &format!("...which requires {}...", query.describe(self))); | |
110 | } | |
111 | ||
112 | err.note(&format!( | |
113 | "...which again requires {}, completing the cycle", | |
114 | stack[0].query.describe(self) | |
115 | )); | |
116 | ||
117 | if let Some((span, query)) = usage { | |
118 | err.span_note( | |
119 | fix_span(span, &query), | |
120 | &format!("cycle used when {}", query.describe(self)), | |
121 | ); | |
122 | } | |
123 | ||
124 | err | |
125 | }) | |
126 | } | |
127 | ||
29967ef6 | 128 | pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) { |
ba9703b0 XL |
129 | eprintln!("query stack during panic:"); |
130 | ||
fc512014 | 131 | // Be careful relying on global state here: this code is called from |
ba9703b0 XL |
132 | // a panic hook, which means that the global `Handler` may be in a weird |
133 | // state if it was responsible for triggering the panic. | |
29967ef6 | 134 | let mut i = 0; |
ba9703b0 XL |
135 | ty::tls::with_context_opt(|icx| { |
136 | if let Some(icx) = icx { | |
137 | let query_map = icx.tcx.queries.try_collect_active_jobs(); | |
138 | ||
139 | let mut current_query = icx.query; | |
ba9703b0 XL |
140 | |
141 | while let Some(query) = current_query { | |
29967ef6 XL |
142 | if Some(i) == num_frames { |
143 | break; | |
144 | } | |
ba9703b0 XL |
145 | let query_info = |
146 | if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) { | |
147 | info | |
148 | } else { | |
149 | break; | |
150 | }; | |
151 | let mut diag = Diagnostic::new( | |
152 | Level::FailureNote, | |
153 | &format!( | |
154 | "#{} [{}] {}", | |
155 | i, | |
156 | query_info.info.query.name(), | |
157 | query_info.info.query.describe(icx.tcx) | |
158 | ), | |
159 | ); | |
160 | diag.span = | |
161 | icx.tcx.sess.source_map().guess_head_span(query_info.info.span).into(); | |
162 | handler.force_print_diagnostic(diag); | |
163 | ||
164 | current_query = query_info.job.parent; | |
165 | i += 1; | |
166 | } | |
167 | } | |
168 | }); | |
169 | ||
29967ef6 XL |
170 | if num_frames == None || num_frames >= Some(i) { |
171 | eprintln!("end of query stack"); | |
172 | } else { | |
173 | eprintln!("we're just showing a limited slice of the query stack"); | |
174 | } | |
ba9703b0 XL |
175 | } |
176 | } | |
177 | ||
178 | macro_rules! handle_cycle_error { | |
179 | ([][$tcx: expr, $error:expr]) => {{ | |
180 | $tcx.report_cycle($error).emit(); | |
181 | Value::from_cycle_error($tcx) | |
182 | }}; | |
183 | ([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{ | |
184 | $tcx.report_cycle($error).emit(); | |
185 | $tcx.sess.abort_if_errors(); | |
186 | unreachable!() | |
187 | }}; | |
188 | ([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{ | |
189 | $tcx.report_cycle($error).delay_as_bug(); | |
190 | Value::from_cycle_error($tcx) | |
191 | }}; | |
192 | ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { | |
193 | handle_cycle_error!([$($($modifiers)*)*][$($args)*]) | |
194 | }; | |
195 | } | |
196 | ||
197 | macro_rules! is_anon { | |
198 | ([]) => {{ | |
199 | false | |
200 | }}; | |
201 | ([anon $($rest:tt)*]) => {{ | |
202 | true | |
203 | }}; | |
204 | ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { | |
205 | is_anon!([$($($modifiers)*)*]) | |
206 | }; | |
207 | } | |
208 | ||
209 | macro_rules! is_eval_always { | |
210 | ([]) => {{ | |
211 | false | |
212 | }}; | |
213 | ([eval_always $($rest:tt)*]) => {{ | |
214 | true | |
215 | }}; | |
216 | ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { | |
217 | is_eval_always!([$($($modifiers)*)*]) | |
218 | }; | |
219 | } | |
220 | ||
221 | macro_rules! query_storage { | |
222 | ([][$K:ty, $V:ty]) => { | |
223 | <<$K as Key>::CacheSelector as CacheSelector<$K, $V>>::Cache | |
224 | }; | |
225 | ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { | |
f9f354fc | 226 | <$ty as CacheSelector<$K, $V>>::Cache |
ba9703b0 XL |
227 | }; |
228 | ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { | |
229 | query_storage!([$($($modifiers)*)*][$($args)*]) | |
230 | }; | |
231 | } | |
232 | ||
233 | macro_rules! hash_result { | |
234 | ([][$hcx:expr, $result:expr]) => {{ | |
235 | dep_graph::hash_result($hcx, &$result) | |
236 | }}; | |
237 | ([no_hash $($rest:tt)*][$hcx:expr, $result:expr]) => {{ | |
238 | None | |
239 | }}; | |
240 | ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { | |
241 | hash_result!([$($($modifiers)*)*][$($args)*]) | |
242 | }; | |
243 | } | |
244 | ||
ba9703b0 XL |
245 | macro_rules! query_helper_param_ty { |
246 | (DefId) => { impl IntoQueryParam<DefId> }; | |
247 | ($K:ty) => { $K }; | |
248 | } | |
249 | ||
29967ef6 | 250 | macro_rules! define_queries { |
ba9703b0 | 251 | (<$tcx:tt> |
29967ef6 XL |
252 | $($(#[$attr:meta])* |
253 | [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { | |
ba9703b0 XL |
254 | |
255 | use std::mem; | |
256 | use crate::{ | |
257 | rustc_data_structures::stable_hasher::HashStable, | |
258 | rustc_data_structures::stable_hasher::StableHasher, | |
259 | ich::StableHashingContext | |
260 | }; | |
ba9703b0 XL |
261 | |
262 | define_queries_struct! { | |
263 | tcx: $tcx, | |
264 | input: ($(([$($modifiers)*] [$($attr)*] [$name]))*) | |
265 | } | |
266 | ||
267 | #[allow(nonstandard_style)] | |
268 | #[derive(Clone, Debug)] | |
269 | pub enum Query<$tcx> { | |
270 | $($(#[$attr])* $name($($K)*)),* | |
271 | } | |
272 | ||
273 | impl<$tcx> Query<$tcx> { | |
274 | pub fn name(&self) -> &'static str { | |
275 | match *self { | |
276 | $(Query::$name(_) => stringify!($name),)* | |
277 | } | |
278 | } | |
279 | ||
280 | pub fn describe(&self, tcx: TyCtxt<$tcx>) -> Cow<'static, str> { | |
281 | let (r, name) = match *self { | |
282 | $(Query::$name(key) => { | |
283 | (queries::$name::describe(tcx, key), stringify!($name)) | |
284 | })* | |
285 | }; | |
286 | if tcx.sess.verbose() { | |
287 | format!("{} [{}]", r, name).into() | |
288 | } else { | |
289 | r | |
290 | } | |
291 | } | |
292 | ||
293 | // FIXME(eddyb) Get more valid `Span`s on queries. | |
294 | pub fn default_span(&self, tcx: TyCtxt<$tcx>, span: Span) -> Span { | |
295 | if !span.is_dummy() { | |
296 | return span; | |
297 | } | |
298 | // The `def_span` query is used to calculate `default_span`, | |
299 | // so exit to avoid infinite recursion. | |
300 | if let Query::def_span(..) = *self { | |
301 | return span | |
302 | } | |
303 | match *self { | |
304 | $(Query::$name(key) => key.default_span(tcx),)* | |
305 | } | |
306 | } | |
307 | } | |
308 | ||
309 | impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> { | |
310 | fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { | |
311 | mem::discriminant(self).hash_stable(hcx, hasher); | |
312 | match *self { | |
313 | $(Query::$name(key) => key.hash_stable(hcx, hasher),)* | |
314 | } | |
315 | } | |
316 | } | |
317 | ||
f035d41b | 318 | #[allow(nonstandard_style)] |
ba9703b0 XL |
319 | pub mod queries { |
320 | use std::marker::PhantomData; | |
321 | ||
f035d41b | 322 | $(pub struct $name<$tcx> { |
ba9703b0 XL |
323 | data: PhantomData<&$tcx ()> |
324 | })* | |
325 | } | |
326 | ||
f035d41b XL |
327 | // HACK(eddyb) this is like the `impl QueryConfig for queries::$name` |
328 | // below, but using type aliases instead of associated types, to bypass | |
329 | // the limitations around normalizing under HRTB - for example, this: | |
330 | // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value` | |
331 | // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`. | |
332 | // This is primarily used by the `provide!` macro in `rustc_metadata`. | |
333 | #[allow(nonstandard_style, unused_lifetimes)] | |
334 | pub mod query_keys { | |
335 | use super::*; | |
336 | ||
337 | $(pub type $name<$tcx> = $($K)*;)* | |
338 | } | |
339 | #[allow(nonstandard_style, unused_lifetimes)] | |
340 | pub mod query_values { | |
341 | use super::*; | |
342 | ||
343 | $(pub type $name<$tcx> = $V;)* | |
344 | } | |
345 | ||
29967ef6 | 346 | $(impl<$tcx> QueryConfig for queries::$name<$tcx> { |
ba9703b0 XL |
347 | type Key = $($K)*; |
348 | type Value = $V; | |
f9f354fc XL |
349 | type Stored = < |
350 | query_storage!([$($modifiers)*][$($K)*, $V]) | |
351 | as QueryStorage | |
352 | >::Stored; | |
ba9703b0 | 353 | const NAME: &'static str = stringify!($name); |
ba9703b0 XL |
354 | } |
355 | ||
356 | impl<$tcx> QueryAccessors<TyCtxt<$tcx>> for queries::$name<$tcx> { | |
357 | const ANON: bool = is_anon!([$($modifiers)*]); | |
358 | const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); | |
29967ef6 | 359 | const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$name; |
ba9703b0 XL |
360 | |
361 | type Cache = query_storage!([$($modifiers)*][$($K)*, $V]); | |
362 | ||
363 | #[inline(always)] | |
29967ef6 | 364 | fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<crate::dep_graph::DepKind, <TyCtxt<$tcx> as QueryContext>::Query, Self::Cache> { |
ba9703b0 XL |
365 | &tcx.queries.$name |
366 | } | |
367 | ||
ba9703b0 XL |
368 | #[inline] |
369 | fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { | |
370 | let provider = tcx.queries.providers.get(key.query_crate()) | |
371 | // HACK(eddyb) it's possible crates may be loaded after | |
372 | // the query engine is created, and because crate loading | |
373 | // is not yet integrated with the query engine, such crates | |
374 | // would be missing appropriate entries in `providers`. | |
375 | .unwrap_or(&tcx.queries.fallback_extern_providers) | |
376 | .$name; | |
377 | provider(tcx, key) | |
378 | } | |
379 | ||
380 | fn hash_result( | |
381 | _hcx: &mut StableHashingContext<'_>, | |
382 | _result: &Self::Value | |
383 | ) -> Option<Fingerprint> { | |
384 | hash_result!([$($modifiers)*][_hcx, _result]) | |
385 | } | |
386 | ||
387 | fn handle_cycle_error( | |
388 | tcx: TyCtxt<'tcx>, | |
389 | error: CycleError<Query<'tcx>> | |
390 | ) -> Self::Value { | |
391 | handle_cycle_error!([$($modifiers)*][tcx, error]) | |
392 | } | |
393 | })* | |
394 | ||
395 | #[derive(Copy, Clone)] | |
396 | pub struct TyCtxtEnsure<'tcx> { | |
397 | pub tcx: TyCtxt<'tcx>, | |
398 | } | |
399 | ||
400 | impl TyCtxtEnsure<$tcx> { | |
401 | $($(#[$attr])* | |
402 | #[inline(always)] | |
403 | pub fn $name(self, key: query_helper_param_ty!($($K)*)) { | |
404 | ensure_query::<queries::$name<'_>, _>(self.tcx, key.into_query_param()) | |
405 | })* | |
406 | } | |
407 | ||
408 | #[derive(Copy, Clone)] | |
409 | pub struct TyCtxtAt<'tcx> { | |
410 | pub tcx: TyCtxt<'tcx>, | |
411 | pub span: Span, | |
412 | } | |
413 | ||
414 | impl Deref for TyCtxtAt<'tcx> { | |
415 | type Target = TyCtxt<'tcx>; | |
416 | #[inline(always)] | |
417 | fn deref(&self) -> &Self::Target { | |
418 | &self.tcx | |
419 | } | |
420 | } | |
421 | ||
422 | impl TyCtxt<$tcx> { | |
423 | /// Returns a transparent wrapper for `TyCtxt`, which ensures queries | |
424 | /// are executed instead of just returning their results. | |
425 | #[inline(always)] | |
426 | pub fn ensure(self) -> TyCtxtEnsure<$tcx> { | |
427 | TyCtxtEnsure { | |
428 | tcx: self, | |
429 | } | |
430 | } | |
431 | ||
432 | /// Returns a transparent wrapper for `TyCtxt` which uses | |
433 | /// `span` as the location of queries performed through it. | |
434 | #[inline(always)] | |
435 | pub fn at(self, span: Span) -> TyCtxtAt<$tcx> { | |
436 | TyCtxtAt { | |
437 | tcx: self, | |
438 | span | |
439 | } | |
440 | } | |
441 | ||
442 | $($(#[$attr])* | |
443 | #[inline(always)] | |
f9f354fc XL |
444 | #[must_use] |
445 | pub fn $name(self, key: query_helper_param_ty!($($K)*)) | |
29967ef6 | 446 | -> <queries::$name<$tcx> as QueryConfig>::Stored |
f9f354fc XL |
447 | { |
448 | self.at(DUMMY_SP).$name(key.into_query_param()) | |
ba9703b0 XL |
449 | })* |
450 | ||
451 | /// All self-profiling events generated by the query engine use | |
452 | /// virtual `StringId`s for their `event_id`. This method makes all | |
453 | /// those virtual `StringId`s point to actual strings. | |
454 | /// | |
455 | /// If we are recording only summary data, the ids will point to | |
456 | /// just the query names. If we are recording query keys too, we | |
457 | /// allocate the corresponding strings here. | |
458 | pub fn alloc_self_profile_query_strings(self) { | |
459 | use crate::ty::query::profiling_support::{ | |
460 | alloc_self_profile_query_strings_for_query_cache, | |
461 | QueryKeyStringCache, | |
462 | }; | |
463 | ||
464 | if !self.prof.enabled() { | |
465 | return; | |
466 | } | |
467 | ||
468 | let mut string_cache = QueryKeyStringCache::new(); | |
469 | ||
470 | $({ | |
471 | alloc_self_profile_query_strings_for_query_cache( | |
472 | self, | |
473 | stringify!($name), | |
474 | &self.queries.$name, | |
475 | &mut string_cache, | |
476 | ); | |
477 | })* | |
478 | } | |
479 | } | |
480 | ||
481 | impl TyCtxtAt<$tcx> { | |
482 | $($(#[$attr])* | |
483 | #[inline(always)] | |
f9f354fc | 484 | pub fn $name(self, key: query_helper_param_ty!($($K)*)) |
29967ef6 | 485 | -> <queries::$name<$tcx> as QueryConfig>::Stored |
f9f354fc | 486 | { |
ba9703b0 XL |
487 | get_query::<queries::$name<'_>, _>(self.tcx, self.span, key.into_query_param()) |
488 | })* | |
489 | } | |
490 | ||
491 | define_provider_struct! { | |
492 | tcx: $tcx, | |
493 | input: ($(([$($modifiers)*] [$name] [$($K)*] [$V]))*) | |
494 | } | |
495 | ||
f035d41b XL |
496 | impl Copy for Providers {} |
497 | impl Clone for Providers { | |
ba9703b0 XL |
498 | fn clone(&self) -> Self { *self } |
499 | } | |
500 | } | |
501 | } | |
502 | ||
f035d41b XL |
503 | // FIXME(eddyb) this macro (and others?) use `$tcx` and `'tcx` interchangeably. |
504 | // We should either not take `$tcx` at all and use `'tcx` everywhere, or use | |
505 | // `$tcx` everywhere (even if that isn't necessary due to lack of hygiene). | |
ba9703b0 XL |
506 | macro_rules! define_queries_struct { |
507 | (tcx: $tcx:tt, | |
508 | input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { | |
509 | pub struct Queries<$tcx> { | |
fc512014 | 510 | /// This provides access to the incremental compilation on-disk cache for query results. |
ba9703b0 XL |
511 | /// Do not access this directly. It is only meant to be used by |
512 | /// `DepGraph::try_mark_green()` and the query infrastructure. | |
fc512014 XL |
513 | /// This is `None` if we are not incremental compilation mode |
514 | pub(crate) on_disk_cache: Option<OnDiskCache<'tcx>>, | |
ba9703b0 | 515 | |
f035d41b XL |
516 | providers: IndexVec<CrateNum, Providers>, |
517 | fallback_extern_providers: Box<Providers>, | |
ba9703b0 XL |
518 | |
519 | $($(#[$attr])* $name: QueryState< | |
29967ef6 XL |
520 | crate::dep_graph::DepKind, |
521 | <TyCtxt<$tcx> as QueryContext>::Query, | |
ba9703b0 XL |
522 | <queries::$name<$tcx> as QueryAccessors<TyCtxt<'tcx>>>::Cache, |
523 | >,)* | |
524 | } | |
525 | ||
526 | impl<$tcx> Queries<$tcx> { | |
527 | pub(crate) fn new( | |
f035d41b XL |
528 | providers: IndexVec<CrateNum, Providers>, |
529 | fallback_extern_providers: Providers, | |
fc512014 | 530 | on_disk_cache: Option<OnDiskCache<'tcx>>, |
ba9703b0 XL |
531 | ) -> Self { |
532 | Queries { | |
533 | providers, | |
534 | fallback_extern_providers: Box::new(fallback_extern_providers), | |
535 | on_disk_cache, | |
536 | $($name: Default::default()),* | |
537 | } | |
538 | } | |
539 | ||
540 | pub(crate) fn try_collect_active_jobs( | |
541 | &self | |
29967ef6 | 542 | ) -> Option<FxHashMap<QueryJobId<crate::dep_graph::DepKind>, QueryJobInfo<crate::dep_graph::DepKind, <TyCtxt<$tcx> as QueryContext>::Query>>> { |
ba9703b0 XL |
543 | let mut jobs = FxHashMap::default(); |
544 | ||
545 | $( | |
546 | self.$name.try_collect_active_jobs( | |
547 | <queries::$name<'tcx> as QueryAccessors<TyCtxt<'tcx>>>::DEP_KIND, | |
548 | Query::$name, | |
549 | &mut jobs, | |
550 | )?; | |
551 | )* | |
552 | ||
553 | Some(jobs) | |
554 | } | |
555 | } | |
556 | }; | |
557 | } | |
558 | ||
559 | macro_rules! define_provider_struct { | |
560 | (tcx: $tcx:tt, | |
561 | input: ($(([$($modifiers:tt)*] [$name:ident] [$K:ty] [$R:ty]))*)) => { | |
f035d41b XL |
562 | pub struct Providers { |
563 | $(pub $name: for<$tcx> fn(TyCtxt<$tcx>, $K) -> $R,)* | |
ba9703b0 XL |
564 | } |
565 | ||
f035d41b | 566 | impl Default for Providers { |
ba9703b0 XL |
567 | fn default() -> Self { |
568 | $(fn $name<$tcx>(_: TyCtxt<$tcx>, key: $K) -> $R { | |
569 | bug!("`tcx.{}({:?})` unsupported by its crate", | |
570 | stringify!($name), key); | |
571 | })* | |
572 | Providers { $($name),* } | |
573 | } | |
574 | } | |
575 | }; | |
576 | } |