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