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