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.
5 use crate::on_disk_cache
::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}
;
6 use crate::profiling_support
::QueryKeyStringCache
;
7 use crate::{on_disk_cache, Queries}
;
8 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher}
;
9 use rustc_data_structures
::sync
::{AtomicU64, Lock}
;
10 use rustc_errors
::{Diagnostic, Handler}
;
11 use rustc_middle
::dep_graph
::{
12 self, DepKind
, DepKindStruct
, DepNode
, DepNodeIndex
, SerializedDepNodeIndex
,
14 use rustc_middle
::query
::Key
;
15 use rustc_middle
::ty
::tls
::{self, ImplicitCtxt}
;
16 use rustc_middle
::ty
::{self, TyCtxt}
;
17 use rustc_query_system
::dep_graph
::{DepNodeParams, HasDepContext}
;
18 use rustc_query_system
::ich
::StableHashingContext
;
19 use rustc_query_system
::query
::{
20 force_query
, QueryConfig
, QueryContext
, QueryJobId
, QueryMap
, QuerySideEffects
, QueryStackFrame
,
22 use rustc_query_system
::{LayoutOfDepth, QueryOverflow, Value}
;
23 use rustc_serialize
::Decodable
;
24 use rustc_session
::Limit
;
25 use rustc_span
::def_id
::LOCAL_CRATE
;
27 use std
::num
::NonZeroU64
;
28 use thin_vec
::ThinVec
;
30 #[derive(Copy, Clone)]
31 pub struct QueryCtxt
<'tcx
> {
32 pub tcx
: TyCtxt
<'tcx
>,
33 pub queries
: &'tcx Queries
<'tcx
>,
36 impl<'tcx
> std
::ops
::Deref
for QueryCtxt
<'tcx
> {
37 type Target
= TyCtxt
<'tcx
>;
40 fn deref(&self) -> &Self::Target
{
45 impl<'tcx
> HasDepContext
for QueryCtxt
<'tcx
> {
46 type DepKind
= rustc_middle
::dep_graph
::DepKind
;
47 type DepContext
= TyCtxt
<'tcx
>;
50 fn dep_context(&self) -> &Self::DepContext
{
55 impl QueryContext
for QueryCtxt
<'_
> {
56 fn next_job_id(self) -> QueryJobId
{
59 self.queries
.jobs
.fetch_add(1, rustc_data_structures
::sync
::Ordering
::Relaxed
),
65 fn current_query_job(self) -> Option
<QueryJobId
> {
66 tls
::with_related_context(*self, |icx
| icx
.query
)
69 fn try_collect_active_jobs(self) -> Option
<QueryMap
<DepKind
>> {
70 self.queries
.try_collect_active_jobs(*self)
73 // Interactions with on_disk_cache
74 fn load_side_effects(self, prev_dep_node_index
: SerializedDepNodeIndex
) -> QuerySideEffects
{
78 .map(|c
| c
.load_side_effects(*self, prev_dep_node_index
))
82 fn store_side_effects(self, dep_node_index
: DepNodeIndex
, side_effects
: QuerySideEffects
) {
83 if let Some(c
) = self.queries
.on_disk_cache
.as_ref() {
84 c
.store_side_effects(dep_node_index
, side_effects
)
88 fn store_side_effects_for_anon_node(
90 dep_node_index
: DepNodeIndex
,
91 side_effects
: QuerySideEffects
,
93 if let Some(c
) = self.queries
.on_disk_cache
.as_ref() {
94 c
.store_side_effects_for_anon_node(dep_node_index
, side_effects
)
98 /// Executes a job by changing the `ImplicitCtxt` to point to the
99 /// new query job while it executes. It returns the diagnostics
100 /// captured during execution and the actual result.
106 diagnostics
: Option
<&Lock
<ThinVec
<Diagnostic
>>>,
107 compute
: impl FnOnce() -> R
,
109 // The `TyCtxt` stored in TLS has the same global interner lifetime
110 // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
111 // when accessing the `ImplicitCtxt`.
112 tls
::with_related_context(*self, move |current_icx
| {
113 if depth_limit
&& !self.recursion_limit().value_within_limit(current_icx
.query_depth
) {
114 self.depth_limit_error(token
);
117 // Update the `ImplicitCtxt` to point to our new query job.
118 let new_icx
= ImplicitCtxt
{
122 query_depth
: current_icx
.query_depth
+ depth_limit
as usize,
123 task_deps
: current_icx
.task_deps
,
126 // Use the `ImplicitCtxt` while we execute the query.
127 tls
::enter_context(&new_icx
, compute
)
131 fn depth_limit_error(self, job
: QueryJobId
) {
133 let mut layout_of_depth
= None
;
134 if let Some(map
) = self.try_collect_active_jobs() {
135 if let Some((info
, depth
)) = job
.try_find_layout_root(map
) {
136 span
= Some(info
.job
.span
);
137 layout_of_depth
= Some(LayoutOfDepth { desc: info.query.description, depth }
);
141 let suggested_limit
= match self.recursion_limit() {
142 Limit(0) => Limit(2),
146 self.sess
.emit_fatal(QueryOverflow
{
150 crate_name
: self.crate_name(LOCAL_CRATE
),
155 impl<'tcx
> QueryCtxt
<'tcx
> {
157 pub fn from_tcx(tcx
: TyCtxt
<'tcx
>) -> Self {
158 let queries
= tcx
.queries
.as_any();
159 let queries
= unsafe {
160 let queries
= std
::mem
::transmute
::<&dyn Any
, &dyn Any
>(queries
);
161 let queries
= queries
.downcast_ref().unwrap();
162 let queries
= std
::mem
::transmute
::<&Queries
<'_
>, &Queries
<'_
>>(queries
);
165 QueryCtxt { tcx, queries }
168 pub(crate) fn on_disk_cache(self) -> Option
<&'tcx on_disk_cache
::OnDiskCache
<'tcx
>> {
169 self.queries
.on_disk_cache
.as_ref()
172 pub(super) fn encode_query_results(
174 encoder
: &mut CacheEncoder
<'_
, 'tcx
>,
175 query_result_index
: &mut EncodedDepNodeIndex
,
177 for query
in &self.queries
.query_structs
{
178 if let Some(encode
) = query
.encode_query_results
{
179 encode(self, encoder
, query_result_index
);
184 pub fn try_print_query_stack(
186 query
: Option
<QueryJobId
>,
188 num_frames
: Option
<usize>,
190 rustc_query_system
::query
::print_query_stack(self, query
, handler
, num_frames
)
194 #[derive(Clone, Copy)]
195 pub(crate) struct QueryStruct
<'tcx
> {
196 pub try_collect_active_jobs
: fn(QueryCtxt
<'tcx
>, &mut QueryMap
<DepKind
>) -> Option
<()>,
197 pub alloc_self_profile_query_strings
: fn(TyCtxt
<'tcx
>, &mut QueryKeyStringCache
),
198 pub encode_query_results
:
199 Option
<fn(QueryCtxt
<'tcx
>, &mut CacheEncoder
<'_
, 'tcx
>, &mut EncodedDepNodeIndex
)>,
202 macro_rules
! handle_cycle_error
{
204 rustc_query_system
::HandleCycleError
::Error
206 ([(fatal_cycle
) $
($rest
:tt
)*]) => {{
207 rustc_query_system
::HandleCycleError
::Fatal
209 ([(cycle_delay_bug
) $
($rest
:tt
)*]) => {{
210 rustc_query_system
::HandleCycleError
::DelayBug
212 ([$other
:tt $
($modifiers
:tt
)*]) => {
213 handle_cycle_error
!([$
($modifiers
)*])
217 macro_rules
! is_anon
{
221 ([(anon
) $
($rest
:tt
)*]) => {{
224 ([$other
:tt $
($modifiers
:tt
)*]) => {
225 is_anon
!([$
($modifiers
)*])
229 macro_rules
! is_eval_always
{
233 ([(eval_always
) $
($rest
:tt
)*]) => {{
236 ([$other
:tt $
($modifiers
:tt
)*]) => {
237 is_eval_always
!([$
($modifiers
)*])
241 macro_rules
! depth_limit
{
245 ([(depth_limit
) $
($rest
:tt
)*]) => {{
248 ([$other
:tt $
($modifiers
:tt
)*]) => {
249 depth_limit
!([$
($modifiers
)*])
253 macro_rules
! feedable
{
257 ([(feedable
) $
($rest
:tt
)*]) => {{
260 ([$other
:tt $
($modifiers
:tt
)*]) => {
261 feedable
!([$
($modifiers
)*])
265 macro_rules
! hash_result
{
267 Some(dep_graph
::hash_result
)
269 ([(no_hash
) $
($rest
:tt
)*]) => {{
272 ([$other
:tt $
($modifiers
:tt
)*]) => {
273 hash_result
!([$
($modifiers
)*])
277 macro_rules
! get_provider
{
278 ([][$tcx
:expr
, $name
:ident
, $key
:expr
]) => {{
279 $tcx
.queries
.local_providers
.$name
281 ([(separate_provide_extern
) $
($rest
:tt
)*][$tcx
:expr
, $name
:ident
, $key
:expr
]) => {{
282 if $key
.query_crate_is_local() {
283 $tcx
.queries
.local_providers
.$name
285 $tcx
.queries
.extern_providers
.$name
288 ([$other
:tt $
($modifiers
:tt
)*][$
($args
:tt
)*]) => {
289 get_provider
!([$
($modifiers
)*][$
($args
)*])
293 macro_rules
! should_ever_cache_on_disk
{
294 ([]$yes
:tt $no
:tt
) => {{
297 ([(cache
) $
($rest
:tt
)*]$yes
:tt $no
:tt
) => {{
300 ([$other
:tt $
($modifiers
:tt
)*]$yes
:tt $no
:tt
) => {
301 should_ever_cache_on_disk
!([$
($modifiers
)*]$yes $no
)
305 pub(crate) fn create_query_frame
<
307 K
: Copy
+ Key
+ for<'a
> HashStable
<StableHashingContext
<'a
>>,
309 tcx
: QueryCtxt
<'tcx
>,
310 do_describe
: fn(TyCtxt
<'tcx
>, K
) -> String
,
314 ) -> QueryStackFrame
<DepKind
> {
315 // Avoid calling queries while formatting the description
316 let description
= ty
::print
::with_no_queries
!(
317 // Disable visible paths printing for performance reasons.
318 // Showing visible path instead of any path is not that important in production.
319 ty
::print
::with_no_visible_paths
!(
320 // Force filename-line mode to avoid invoking `type_of` query.
321 ty
::print
::with_forced_impl_filename_line
!(do_describe(tcx
.tcx
, key
))
325 if tcx
.sess
.verbose() { format!("{description}
[{name:?}
]") } else { description };
326 let span = if kind == dep_graph::DepKind::def_span {
327 // The `def_span` query is used to calculate `default_span`,
328 // so exit to avoid infinite recursion.
331 Some(key.default_span(*tcx))
333 let def_id = key.key_as_def_id();
334 let def_kind = if kind == dep_graph::DepKind::opt_def_kind {
335 // Try to avoid infinite recursion.
338 def_id.and_then(|def_id| def_id.as_local()).and_then(|def_id| tcx.opt_def_kind(def_id))
341 tcx.with_stable_hashing_context(|mut hcx| {
342 let mut hasher = StableHasher::new();
343 std::mem::discriminant(&kind).hash_stable(&mut hcx, &mut hasher);
344 key.hash_stable(&mut hcx, &mut hasher);
345 hasher.finish::<u64>()
348 let ty_adt_id = key.ty_adt_id();
350 QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
353 fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
355 Q: QueryConfig<QueryCtxt<'tcx>>,
356 Q::Key: DepNodeParams<TyCtxt<'tcx>>,
358 debug_assert!(tcx.dep_graph.is_green(&dep_node));
360 let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
361 panic!("Failed to recover key
for {:?} with hash {}
", dep_node, dep_node.hash)
363 if Q::cache_on_disk(tcx, &key) {
364 let _ = Q::execute_query(tcx, key);
368 pub(crate) fn try_load_from_disk<'tcx, V>(
369 tcx: QueryCtxt<'tcx>,
370 id: SerializedDepNodeIndex,
373 V: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
375 tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
378 fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
380 Q: QueryConfig<QueryCtxt<'tcx>>,
381 Q::Key: DepNodeParams<TyCtxt<'tcx>>,
382 Q::Value: Value<TyCtxt<'tcx>, DepKind>,
384 // We must avoid ever having to call `force_from_dep_node()` for a
385 // `DepNode::codegen_unit`:
386 // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
387 // would always end up having to evaluate the first caller of the
388 // `codegen_unit` query that *is* reconstructible. This might very well be
389 // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
390 // to re-trigger calling the `codegen_unit` query with the right key. At
391 // that point we would already have re-done all the work we are trying to
392 // avoid doing in the first place.
393 // The solution is simple: Just explicitly call the `codegen_unit` query for
394 // each CGU, right after partitioning. This way `try_mark_green` will always
395 // hit the cache instead of having to go through `force_from_dep_node`.
396 // This assertion makes sure, we actually keep applying the solution above.
398 dep_node.kind != DepKind::codegen_unit,
399 "calling
force_from_dep_node() on DepKind
::codegen_unit
"
402 if let Some(key) = Q::Key::recover(tcx, &dep_node) {
403 #[cfg(debug_assertions)]
404 let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
405 let tcx = QueryCtxt::from_tcx(tcx);
406 force_query::<Q, _, DepKind>(tcx, key, dep_node);
413 pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
415 Q: QueryConfig<QueryCtxt<'tcx>>,
416 Q::Key: DepNodeParams<TyCtxt<'tcx>>,
418 let fingerprint_style = Q::Key::fingerprint_style();
420 if is_anon || !fingerprint_style.reconstructible() {
421 return DepKindStruct {
425 force_from_dep_node: None,
426 try_load_from_on_disk_cache: None,
434 force_from_dep_node: Some(force_from_dep_node::<Q>),
435 try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::<Q>),
439 macro_rules! expand_if_cached {
440 ([], $tokens:expr) => {{
443 ([(cache) $($rest:tt)*], $tokens:expr) => {{
446 ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
447 expand_if_cached!([$($modifiers)*], $tokens)
451 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
452 // invoked by `rustc_query_append`.
453 macro_rules! define_queries {
456 [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
457 define_queries_struct! {
458 input: ($(([$($modifiers)*] [$($attr)*] [$name]))*)
461 #[allow(nonstandard_style)]
463 use std::marker::PhantomData;
465 $(pub struct $name<'tcx> {
466 data: PhantomData<&'tcx ()>
470 $(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
471 type Key = query_keys::$name<'tcx>;
472 type Value = query_values::$name<'tcx>;
473 const NAME: &'static str = stringify!($name);
476 fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
477 ::rustc_middle::query::cached::$name(tcx, key)
480 type Cache = query_storage::$name<'tcx>;
483 fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
484 where QueryCtxt<'tcx>: 'a
490 fn query_cache<'a>(tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
493 &tcx.query_system.caches.$name
496 fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
501 #[allow(unused_variables)]
502 fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
503 query_provided_to_value::$name(
505 get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
510 fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
511 should_ever_cache_on_disk!([$($modifiers)*] {
512 if Self::cache_on_disk(_qcx.tcx, _key) {
513 Some(|qcx: QueryCtxt<'tcx>, dep_node| {
514 let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
518 value.map(|value| query_provided_to_value::$name(qcx.tcx, value))
528 const ANON: bool = is_anon!([$($modifiers)*]);
529 const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
530 const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]);
531 const FEEDABLE: bool = feedable!([$($modifiers)*]);
533 const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name;
534 const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]);
536 const HASH_RESULT: rustc_query_system::query::HashResult<QueryCtxt<'tcx>, Self> = hash_result!([$($modifiers)*]);
539 #[allow(nonstandard_style)]
540 mod query_callbacks {
542 use rustc_query_system::dep_graph::FingerprintStyle;
544 // We use this for most things when incr. comp. is turned off.
545 pub fn Null<'tcx>() -> DepKindStruct<'tcx> {
548 is_eval_always: false,
549 fingerprint_style: FingerprintStyle::Unit,
550 force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node
: encountered {:?}
", dep_node)),
551 try_load_from_on_disk_cache: None,
555 // We use this for the forever-red node.
556 pub fn Red<'tcx>() -> DepKindStruct<'tcx> {
559 is_eval_always: false,
560 fingerprint_style: FingerprintStyle::Unit,
561 force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node
: encountered {:?}
", dep_node)),
562 try_load_from_on_disk_cache: None,
566 pub fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
569 is_eval_always: false,
570 fingerprint_style: FingerprintStyle::Unit,
571 force_from_dep_node: None,
572 try_load_from_on_disk_cache: None,
576 pub fn CompileCodegenUnit<'tcx>() -> DepKindStruct<'tcx> {
579 is_eval_always: false,
580 fingerprint_style: FingerprintStyle::Opaque,
581 force_from_dep_node: None,
582 try_load_from_on_disk_cache: None,
586 pub fn CompileMonoItem<'tcx>() -> DepKindStruct<'tcx> {
589 is_eval_always: false,
590 fingerprint_style: FingerprintStyle::Opaque,
591 force_from_dep_node: None,
592 try_load_from_on_disk_cache: None,
596 $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
597 $crate::plumbing::query_callback::<queries::$name<'tcx>>(
598 is_anon!([$($modifiers)*]),
599 is_eval_always!([$($modifiers)*]),
605 use rustc_middle::ty::TyCtxt;
606 use $crate::plumbing::{QueryStruct, QueryCtxt};
607 use $crate::profiling_support::QueryKeyStringCache;
608 use rustc_query_system::query::QueryMap;
609 use rustc_middle::dep_graph::DepKind;
611 pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
612 fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap<DepKind>) -> Option<()> {
615 fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
618 try_collect_active_jobs: noop_try_collect_active_jobs,
619 alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
620 encode_query_results: None,
624 pub(super) use dummy_query_struct as Null;
625 pub(super) use dummy_query_struct as Red;
626 pub(super) use dummy_query_struct as TraitSelect;
627 pub(super) use dummy_query_struct as CompileCodegenUnit;
628 pub(super) use dummy_query_struct as CompileMonoItem;
631 pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
632 try_collect_active_jobs: |tcx, qmap| {
633 let make_query = |tcx, key| {
634 let kind = rustc_middle::dep_graph::DepKind::$name;
635 let name = stringify!($name);
636 $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
638 tcx.queries.$name.try_collect_active_jobs(
644 alloc_self_profile_query_strings: |tcx, string_cache| {
645 $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
648 &tcx.query_system.caches.$name,
652 encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
653 $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
658 pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
659 arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
664 use crate::{ExternProviders, OnDiskCache, Providers};
666 impl<'tcx> Queries<'tcx> {
668 local_providers: Providers,
669 extern_providers: ExternProviders,
670 on_disk_cache: Option<OnDiskCache<'tcx>>,
672 use crate::query_structs;
674 local_providers: Box::new(local_providers),
675 extern_providers: Box::new(extern_providers),
676 query_structs: make_dep_kind_array!(query_structs).to_vec(),
678 jobs: AtomicU64::new(1),
684 macro_rules! define_queries_struct {
686 input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
688 pub struct Queries<'tcx> {
689 local_providers: Box<Providers>,
690 extern_providers: Box<ExternProviders>,
691 query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,
692 pub on_disk_cache: Option<OnDiskCache<'tcx>>,
698 <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
699 rustc_middle::dep_graph::DepKind,
704 impl<'tcx> Queries<'tcx> {
705 pub(crate) fn try_collect_active_jobs(
708 ) -> Option<QueryMap<rustc_middle::dep_graph::DepKind>> {
709 let tcx = QueryCtxt { tcx, queries: self };
710 let mut jobs = QueryMap::default();
712 for query in &self.query_structs {
713 (query.try_collect_active_jobs)(tcx, &mut jobs);
720 impl<'tcx> QueryEngine<'tcx> for Queries<'tcx> {
721 fn as_any(&'tcx self) -> &'tcx dyn std::any::Any {
722 let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) };
726 fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool {
727 let qcx = QueryCtxt { tcx, queries: self };
728 tcx.dep_graph.try_mark_green(qcx, dep_node).is_some()
733 #[tracing::instrument(level = "trace
", skip(self, tcx), ret)]
738 key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
740 ) -> Option<query_values::$name<'tcx>> {
741 let qcx = QueryCtxt { tcx, queries: self };
742 get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)