|
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 | 1 | use std::num::NonZero; |
6 | 2 |
|
7 | 3 | use rustc_data_structures::sync::{DynSend, DynSync}; |
@@ -29,10 +25,8 @@ use rustc_span::def_id::LOCAL_CRATE; |
29 | 25 | use crate::error::{QueryOverflow, QueryOverflowNote}; |
30 | 26 | use crate::execution::{all_inactive, force_query}; |
31 | 27 | use crate::job::find_dep_kind_root; |
32 | | -use crate::{ |
33 | | - CollectActiveJobsKind, GetQueryVTable, collect_active_jobs_from_all_queries, |
34 | | - for_each_query_vtable, |
35 | | -}; |
| 28 | +use crate::query_impl::for_each_query_vtable; |
| 29 | +use crate::{CollectActiveJobsKind, GetQueryVTable, collect_active_jobs_from_all_queries}; |
36 | 30 |
|
37 | 31 | fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) { |
38 | 32 | let job_map = collect_active_jobs_from_all_queries(tcx, CollectActiveJobsKind::Full); |
@@ -283,256 +277,3 @@ pub(crate) fn force_from_dep_node_inner<'tcx, Q: GetQueryVTable<'tcx>>( |
283 | 277 | false |
284 | 278 | } |
285 | 279 | } |
286 | | - |
287 | | -macro_rules! define_queries { |
288 | | - ( |
289 | | - // Note: `$K` and `$V` are unused but present so this can be called by |
290 | | - // `rustc_with_all_queries`. |
291 | | - queries { |
292 | | - $( |
293 | | - $(#[$attr:meta])* |
294 | | - fn $name:ident($K:ty) -> $V:ty |
295 | | - { |
296 | | - // Search for (QMODLIST) to find all occurrences of this query modifier list. |
297 | | - anon: $anon:literal, |
298 | | - arena_cache: $arena_cache:literal, |
299 | | - cache_on_disk: $cache_on_disk:literal, |
300 | | - depth_limit: $depth_limit:literal, |
301 | | - eval_always: $eval_always:literal, |
302 | | - feedable: $feedable:literal, |
303 | | - no_hash: $no_hash:literal, |
304 | | - returns_error_guaranteed: $returns_error_guaranteed:literal, |
305 | | - separate_provide_extern: $separate_provide_extern:literal, |
306 | | - } |
307 | | - )* |
308 | | - } |
309 | | - // Non-queries are unused here. |
310 | | - non_queries { $($_:tt)* } |
311 | | - ) => { |
312 | | - pub(crate) mod query_impl { $(pub(crate) mod $name { |
313 | | - use super::super::*; |
314 | | - use ::rustc_middle::query::erase::{self, Erased}; |
315 | | - |
316 | | - // It seems to be important that every query has its own monomorphic |
317 | | - // copy of `execute_query_incr` and `execute_query_non_incr`. |
318 | | - // Trying to inline these wrapper functions into their generic |
319 | | - // "inner" helpers tends to break `tests/run-make/short-ice`. |
320 | | - |
321 | | - pub(crate) mod execute_query_incr { |
322 | | - use super::*; |
323 | | - |
324 | | - // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames |
325 | | - // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming |
326 | | - #[inline(never)] |
327 | | - pub(crate) fn __rust_end_short_backtrace<'tcx>( |
328 | | - tcx: TyCtxt<'tcx>, |
329 | | - span: Span, |
330 | | - key: queries::$name::Key<'tcx>, |
331 | | - mode: QueryMode, |
332 | | - ) -> Option<Erased<queries::$name::Value<'tcx>>> { |
333 | | - #[cfg(debug_assertions)] |
334 | | - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); |
335 | | - execution::execute_query_incr_inner( |
336 | | - &tcx.query_system.query_vtables.$name, |
337 | | - tcx, |
338 | | - span, |
339 | | - key, |
340 | | - mode |
341 | | - ) |
342 | | - } |
343 | | - } |
344 | | - |
345 | | - pub(crate) mod execute_query_non_incr { |
346 | | - use super::*; |
347 | | - |
348 | | - #[inline(never)] |
349 | | - pub(crate) fn __rust_end_short_backtrace<'tcx>( |
350 | | - tcx: TyCtxt<'tcx>, |
351 | | - span: Span, |
352 | | - key: queries::$name::Key<'tcx>, |
353 | | - __mode: QueryMode, |
354 | | - ) -> Option<Erased<queries::$name::Value<'tcx>>> { |
355 | | - Some(execution::execute_query_non_incr_inner( |
356 | | - &tcx.query_system.query_vtables.$name, |
357 | | - tcx, |
358 | | - span, |
359 | | - key, |
360 | | - )) |
361 | | - } |
362 | | - } |
363 | | - |
364 | | - /// Defines an `invoke_provider` function that calls the query's provider, |
365 | | - /// to be used as a function pointer in the query's vtable. |
366 | | - /// |
367 | | - /// To mark a short-backtrace boundary, the function's actual name |
368 | | - /// (after demangling) must be `__rust_begin_short_backtrace`. |
369 | | - mod invoke_provider_fn { |
370 | | - use super::*; |
371 | | - use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased}; |
372 | | - |
373 | | - #[inline(never)] |
374 | | - pub(crate) fn __rust_begin_short_backtrace<'tcx>( |
375 | | - tcx: TyCtxt<'tcx>, |
376 | | - key: Key<'tcx>, |
377 | | - ) -> Erased<Value<'tcx>> { |
378 | | - #[cfg(debug_assertions)] |
379 | | - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); |
380 | | - |
381 | | - // Call the actual provider function for this query. |
382 | | - |
383 | | - #[cfg($separate_provide_extern)] |
384 | | - let provided_value = if let Some(local_key) = key.as_local_key() { |
385 | | - (tcx.query_system.local_providers.$name)(tcx, local_key) |
386 | | - } else { |
387 | | - (tcx.query_system.extern_providers.$name)(tcx, key) |
388 | | - }; |
389 | | - |
390 | | - #[cfg(not($separate_provide_extern))] |
391 | | - let provided_value = (tcx.query_system.local_providers.$name)(tcx, key); |
392 | | - |
393 | | - rustc_middle::ty::print::with_reduced_queries!({ |
394 | | - tracing::trace!(?provided_value); |
395 | | - }); |
396 | | - |
397 | | - // Erase the returned value, because `QueryVTable` uses erased values. |
398 | | - // For queries with `arena_cache`, this also arena-allocates the value. |
399 | | - provided_to_erased(tcx, provided_value) |
400 | | - } |
401 | | - } |
402 | | - |
403 | | - pub(crate) fn make_query_vtable<'tcx>(incremental: bool) |
404 | | - -> QueryVTable<'tcx, queries::$name::Cache<'tcx>> |
405 | | - { |
406 | | - QueryVTable { |
407 | | - name: stringify!($name), |
408 | | - anon: $anon, |
409 | | - eval_always: $eval_always, |
410 | | - depth_limit: $depth_limit, |
411 | | - feedable: $feedable, |
412 | | - dep_kind: dep_graph::DepKind::$name, |
413 | | - state: Default::default(), |
414 | | - cache: Default::default(), |
415 | | - |
416 | | - invoke_provider_fn: self::invoke_provider_fn::__rust_begin_short_backtrace, |
417 | | - |
418 | | - #[cfg($cache_on_disk)] |
419 | | - will_cache_on_disk_for_key_fn: |
420 | | - rustc_middle::queries::_cache_on_disk_if_fns::$name, |
421 | | - #[cfg(not($cache_on_disk))] |
422 | | - will_cache_on_disk_for_key_fn: |_, _| false, |
423 | | - |
424 | | - #[cfg($cache_on_disk)] |
425 | | - try_load_from_disk_fn: |tcx, key, prev_index, index| { |
426 | | - // Check the `cache_on_disk_if` condition for this key. |
427 | | - if !rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) { |
428 | | - return None; |
429 | | - } |
430 | | - |
431 | | - let value: queries::$name::ProvidedValue<'tcx> = |
432 | | - $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?; |
433 | | - |
434 | | - // Arena-alloc the value if appropriate, and erase it. |
435 | | - Some(queries::$name::provided_to_erased(tcx, value)) |
436 | | - }, |
437 | | - #[cfg(not($cache_on_disk))] |
438 | | - try_load_from_disk_fn: |_tcx, _key, _prev_index, _index| None, |
439 | | - |
440 | | - #[cfg($cache_on_disk)] |
441 | | - is_loadable_from_disk_fn: |tcx, key, index| -> bool { |
442 | | - rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && |
443 | | - $crate::plumbing::loadable_from_disk(tcx, index) |
444 | | - }, |
445 | | - #[cfg(not($cache_on_disk))] |
446 | | - is_loadable_from_disk_fn: |_tcx, _key, _index| false, |
447 | | - |
448 | | - // The default just emits `err` and then aborts. |
449 | | - // `from_cycle_error::specialize_query_vtables` overwrites this default for |
450 | | - // certain queries. |
451 | | - value_from_cycle_error: |_tcx, _key, _cycle, err| { |
452 | | - $crate::from_cycle_error::default(err) |
453 | | - }, |
454 | | - |
455 | | - #[cfg($no_hash)] |
456 | | - hash_value_fn: None, |
457 | | - #[cfg(not($no_hash))] |
458 | | - hash_value_fn: Some(|hcx, erased_value: &erase::Erased<queries::$name::Value<'tcx>>| { |
459 | | - let value = erase::restore_val(*erased_value); |
460 | | - rustc_middle::dep_graph::hash_result(hcx, &value) |
461 | | - }), |
462 | | - |
463 | | - format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)), |
464 | | - create_tagged_key: TaggedQueryKey::$name, |
465 | | - execute_query_fn: if incremental { |
466 | | - query_impl::$name::execute_query_incr::__rust_end_short_backtrace |
467 | | - } else { |
468 | | - query_impl::$name::execute_query_non_incr::__rust_end_short_backtrace |
469 | | - }, |
470 | | - } |
471 | | - } |
472 | | - |
473 | | - /// Marker type that implements [`GetQueryVTable`] for this query. |
474 | | - pub(crate) enum VTableGetter {} |
475 | | - |
476 | | - impl<'tcx> GetQueryVTable<'tcx> for VTableGetter { |
477 | | - type Cache = rustc_middle::queries::$name::Cache<'tcx>; |
478 | | - |
479 | | - #[inline(always)] |
480 | | - fn query_vtable(tcx: TyCtxt<'tcx>) -> &'tcx QueryVTable<'tcx, Self::Cache> { |
481 | | - &tcx.query_system.query_vtables.$name |
482 | | - } |
483 | | - } |
484 | | - })*} |
485 | | - |
486 | | - pub fn make_query_vtables<'tcx>(incremental: bool) -> queries::QueryVTables<'tcx> { |
487 | | - queries::QueryVTables { |
488 | | - $( |
489 | | - $name: query_impl::$name::make_query_vtable(incremental), |
490 | | - )* |
491 | | - } |
492 | | - } |
493 | | - |
494 | | - /// Given a filter condition (e.g. `ALL` or `CACHE_ON_DISK`), a `tcx`, |
495 | | - /// and a closure expression that accepts `&QueryVTable`, this macro |
496 | | - /// calls that closure with each query vtable that satisfies the filter |
497 | | - /// condition. |
498 | | - /// |
499 | | - /// This needs to be a macro, because the vtables can have different |
500 | | - /// key/value/cache types for different queries. |
501 | | - /// |
502 | | - /// This macro's argument syntax is specifically intended to look like |
503 | | - /// plain Rust code, so that `for_each_query_vtable!(..)` calls will be |
504 | | - /// formatted by rustfmt. |
505 | | - /// |
506 | | - /// To avoid too much nested-macro complication, filter conditions are |
507 | | - /// implemented by hand as needed. |
508 | | - macro_rules! for_each_query_vtable { |
509 | | - // Call with all queries. |
510 | | - (ALL, $tcx:expr, $closure:expr) => {{ |
511 | | - let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx; |
512 | | - $( |
513 | | - let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> = |
514 | | - &tcx.query_system.query_vtables.$name; |
515 | | - $closure(query); |
516 | | - )* |
517 | | - }}; |
518 | | - |
519 | | - // Only call with queries that can potentially cache to disk. |
520 | | - // |
521 | | - // This allows the use of trait bounds that only need to be satisfied |
522 | | - // by the subset of queries that actually cache to disk. |
523 | | - (CACHE_ON_DISK, $tcx:expr, $closure:expr) => {{ |
524 | | - let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx; |
525 | | - $( |
526 | | - #[cfg($cache_on_disk)] |
527 | | - { |
528 | | - let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> = |
529 | | - &tcx.query_system.query_vtables.$name; |
530 | | - $closure(query); |
531 | | - } |
532 | | - )* |
533 | | - }} |
534 | | - } |
535 | | - |
536 | | - pub(crate) use for_each_query_vtable; |
537 | | - } |
538 | | -} |
0 commit comments