2020-03-19 14:24:21 +01:00
//! The implementation of the query system itself. This defines the macros that
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
2022-08-11 20:36:13 -05:00
use crate ::keys ::Key ;
2021-10-17 17:37:20 +02:00
use crate ::{ on_disk_cache , Queries } ;
2022-08-17 14:22:30 +10:00
use rustc_data_structures ::stable_hasher ::{ HashStable , StableHasher } ;
use rustc_data_structures ::sync ::Lock ;
use rustc_errors ::{ Diagnostic , Handler } ;
2022-08-23 23:31:12 -05:00
use rustc_middle ::dep_graph ::{
self , DepKind , DepKindStruct , DepNode , DepNodeIndex , SerializedDepNodeIndex ,
} ;
2021-01-19 20:40:16 +01:00
use rustc_middle ::ty ::tls ::{ self , ImplicitCtxt } ;
2022-08-11 20:36:13 -05:00
use rustc_middle ::ty ::{ self , TyCtxt } ;
2022-08-23 22:24:39 -05:00
use rustc_query_system ::dep_graph ::{ DepNodeParams , HasDepContext } ;
2022-08-11 20:36:13 -05:00
use rustc_query_system ::ich ::StableHashingContext ;
use rustc_query_system ::query ::{
2022-08-23 23:31:12 -05:00
force_query , QueryConfig , QueryContext , QueryDescription , QueryJobId , QueryMap ,
QuerySideEffects , QueryStackFrame ,
2022-08-11 20:36:13 -05:00
} ;
2021-06-28 21:12:01 +02:00
use std ::any ::Any ;
2022-02-07 11:03:51 -05:00
use std ::num ::NonZeroU64 ;
2022-08-17 14:22:30 +10:00
use thin_vec ::ThinVec ;
2021-06-28 21:12:01 +02:00
2020-04-08 17:03:34 +02:00
#[ derive(Copy, Clone) ]
2020-10-11 10:34:13 +02:00
pub struct QueryCtxt < ' tcx > {
pub tcx : TyCtxt < ' tcx > ,
2021-06-28 21:12:01 +02:00
pub queries : & ' tcx Queries < ' tcx > ,
2020-10-11 10:34:13 +02:00
}
2020-04-08 17:03:34 +02:00
impl < ' tcx > std ::ops ::Deref for QueryCtxt < ' tcx > {
type Target = TyCtxt < ' tcx > ;
2021-05-12 13:19:57 +02:00
#[ inline ]
2020-04-08 17:03:34 +02:00
fn deref ( & self ) -> & Self ::Target {
2020-10-11 10:34:13 +02:00
& self . tcx
2020-04-08 17:03:34 +02:00
}
}
2021-12-14 12:13:07 -05:00
impl < ' tcx > HasDepContext for QueryCtxt < ' tcx > {
2021-01-19 20:40:16 +01:00
type DepKind = rustc_middle ::dep_graph ::DepKind ;
2020-04-08 17:03:34 +02:00
type DepContext = TyCtxt < ' tcx > ;
#[ inline ]
fn dep_context ( & self ) -> & Self ::DepContext {
2020-10-11 10:34:13 +02:00
& self . tcx
2020-04-08 17:03:34 +02:00
}
}
2021-12-14 12:13:07 -05:00
impl QueryContext for QueryCtxt < '_ > {
2022-02-07 11:03:51 -05:00
fn next_job_id ( & self ) -> QueryJobId {
QueryJobId (
NonZeroU64 ::new (
self . queries . jobs . fetch_add ( 1 , rustc_data_structures ::sync ::Ordering ::Relaxed ) ,
)
. unwrap ( ) ,
)
}
fn current_query_job ( & self ) -> Option < QueryJobId > {
2020-04-08 17:03:34 +02:00
tls ::with_related_context ( * * self , | icx | icx . query )
2020-03-19 14:24:21 +01:00
}
2022-02-07 11:03:51 -05:00
fn try_collect_active_jobs ( & self ) -> Option < QueryMap > {
2020-12-26 16:36:55 +01:00
self . queries . try_collect_active_jobs ( * * self )
2020-03-19 14:24:21 +01:00
}
2021-01-18 23:53:42 +01:00
// Interactions with on_disk_cache
2021-07-23 16:40:26 -05:00
fn load_side_effects ( & self , prev_dep_node_index : SerializedDepNodeIndex ) -> QuerySideEffects {
2021-06-28 21:12:01 +02:00
self . queries
. on_disk_cache
2021-01-18 23:53:42 +01:00
. as_ref ( )
2021-07-23 16:40:26 -05:00
. map ( | c | c . load_side_effects ( * * self , prev_dep_node_index ) )
2021-01-18 23:53:42 +01:00
. unwrap_or_default ( )
}
2021-07-23 16:40:26 -05:00
fn store_side_effects ( & self , dep_node_index : DepNodeIndex , side_effects : QuerySideEffects ) {
2021-06-28 21:12:01 +02:00
if let Some ( c ) = self . queries . on_disk_cache . as_ref ( ) {
2021-07-23 16:40:26 -05:00
c . store_side_effects ( dep_node_index , side_effects )
2021-01-18 23:53:42 +01:00
}
}
2021-07-23 16:40:26 -05:00
fn store_side_effects_for_anon_node (
2021-01-18 23:53:42 +01:00
& self ,
dep_node_index : DepNodeIndex ,
2021-07-23 16:40:26 -05:00
side_effects : QuerySideEffects ,
2021-01-18 23:53:42 +01:00
) {
2021-06-28 21:12:01 +02:00
if let Some ( c ) = self . queries . on_disk_cache . as_ref ( ) {
2021-07-23 16:40:26 -05:00
c . store_side_effects_for_anon_node ( dep_node_index , side_effects )
2021-01-18 23:53:42 +01:00
}
}
2020-03-19 14:24:21 +01:00
/// Executes a job by changing the `ImplicitCtxt` to point to the
/// new query job while it executes. It returns the diagnostics
/// captured during execution and the actual result.
#[ inline(always) ]
fn start_query < R > (
& self ,
2022-02-07 11:03:51 -05:00
token : QueryJobId ,
2022-08-24 09:42:12 +08:00
depth_limit : bool ,
2020-03-19 14:24:21 +01:00
diagnostics : Option < & Lock < ThinVec < Diagnostic > > > ,
2020-10-18 21:01:36 +02:00
compute : impl FnOnce ( ) -> R ,
2020-03-19 14:24:21 +01:00
) -> R {
// The `TyCtxt` stored in TLS has the same global interner lifetime
// as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
// when accessing the `ImplicitCtxt`.
2020-04-08 17:03:34 +02:00
tls ::with_related_context ( * * self , move | current_icx | {
2022-08-24 09:42:12 +08:00
if depth_limit & & ! self . recursion_limit ( ) . value_within_limit ( current_icx . query_depth ) {
self . depth_limit_error ( ) ;
}
2020-03-19 14:24:21 +01:00
// Update the `ImplicitCtxt` to point to our new query job.
let new_icx = ImplicitCtxt {
2020-04-08 17:03:34 +02:00
tcx : * * self ,
2020-03-19 14:24:21 +01:00
query : Some ( token ) ,
diagnostics ,
2022-08-24 09:42:12 +08:00
query_depth : current_icx . query_depth + depth_limit as usize ,
2020-03-19 14:24:21 +01:00
task_deps : current_icx . task_deps ,
} ;
// Use the `ImplicitCtxt` while we execute the query.
2018-11-02 16:14:24 +01:00
tls ::enter_context ( & new_icx , | _ | {
2020-10-18 21:01:36 +02:00
rustc_data_structures ::stack ::ensure_sufficient_stack ( compute )
2018-11-02 16:14:24 +01:00
} )
2020-03-19 14:24:21 +01:00
} )
}
}
2020-04-08 17:03:34 +02:00
impl < ' tcx > QueryCtxt < ' tcx > {
2021-06-28 21:12:01 +02:00
#[ inline ]
pub fn from_tcx ( tcx : TyCtxt < ' tcx > ) -> Self {
let queries = tcx . queries . as_any ( ) ;
let queries = unsafe {
let queries = std ::mem ::transmute ::< & dyn Any , & dyn Any > ( queries ) ;
let queries = queries . downcast_ref ( ) . unwrap ( ) ;
let queries = std ::mem ::transmute ::< & Queries < '_ > , & Queries < '_ > > ( queries ) ;
queries
} ;
QueryCtxt { tcx , queries }
}
2022-05-20 19:51:09 -04:00
pub ( crate ) fn on_disk_cache ( self ) -> Option < & ' tcx on_disk_cache ::OnDiskCache < ' tcx > > {
2021-06-28 21:12:01 +02:00
self . queries . on_disk_cache . as_ref ( )
}
2020-10-11 10:34:13 +02:00
pub ( super ) fn encode_query_results (
self ,
2022-06-16 16:00:25 +10:00
encoder : & mut on_disk_cache ::CacheEncoder < '_ , ' tcx > ,
2021-07-23 16:40:26 -05:00
query_result_index : & mut on_disk_cache ::EncodedDepNodeIndex ,
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.
Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).
This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.
This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.
Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
`into_inner` method is changed into `finish`, which returns
`Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
strategy. Its `Ok` type is a `usize`, returning the number of bytes
written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 13:30:45 +10:00
) {
2020-10-11 10:34:13 +02:00
macro_rules ! encode_queries {
( $( $query :ident , ) * ) = > {
$(
2021-01-19 20:40:16 +01:00
on_disk_cache ::encode_query_results ::< _ , super ::queries ::$query < '_ > > (
2020-10-11 10:34:13 +02:00
self ,
encoder ,
query_result_index
Use delayed error handling for `Encodable` and `Encoder` infallible.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.
Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).
This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.
This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.
Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
`into_inner` method is changed into `finish`, which returns
`Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
strategy. Its `Ok` type is a `usize`, returning the number of bytes
written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
passed a mutable reference, e.g. `serialize_query_result_cache`.
2022-06-07 13:30:45 +10:00
) ;
2020-10-11 10:34:13 +02:00
) *
}
}
rustc_cached_queries! ( encode_queries ! ) ;
}
2021-06-28 21:12:01 +02:00
pub fn try_print_query_stack (
self ,
2022-02-07 11:03:51 -05:00
query : Option < QueryJobId > ,
2021-06-28 21:12:01 +02:00
handler : & Handler ,
num_frames : Option < usize > ,
) -> usize {
rustc_query_system ::query ::print_query_stack ( self , query , handler , num_frames )
}
2020-04-08 17:03:34 +02:00
}
2020-03-19 14:24:21 +01:00
macro_rules ! handle_cycle_error {
( [ ] [ $tcx : expr , $error :expr ] ) = > { {
2020-11-29 00:21:56 +01:00
$error . emit ( ) ;
2020-03-19 14:24:21 +01:00
Value ::from_cycle_error ( $tcx )
} } ;
2021-05-30 16:45:51 +02:00
( [ ( fatal_cycle ) $( $rest :tt ) * ] [ $tcx :expr , $error :expr ] ) = > { {
2020-11-29 00:21:56 +01:00
$error . emit ( ) ;
2020-03-19 14:24:21 +01:00
$tcx . sess . abort_if_errors ( ) ;
unreachable! ( )
} } ;
2021-05-30 16:45:51 +02:00
( [ ( cycle_delay_bug ) $( $rest :tt ) * ] [ $tcx :expr , $error :expr ] ) = > { {
2020-11-29 00:21:56 +01:00
$error . delay_as_bug ( ) ;
2020-03-19 14:24:21 +01:00
Value ::from_cycle_error ( $tcx )
} } ;
2021-05-30 16:45:51 +02:00
( [ $other :tt $( $modifiers :tt ) * ] [ $( $args :tt ) * ] ) = > {
handle_cycle_error! ( [ $( $modifiers ) * ] [ $( $args ) * ] )
2020-03-19 14:24:21 +01:00
} ;
}
macro_rules ! is_anon {
( [ ] ) = > { {
false
} } ;
2021-05-30 16:45:51 +02:00
( [ ( anon ) $( $rest :tt ) * ] ) = > { {
2020-03-19 14:24:21 +01:00
true
} } ;
2021-05-30 16:45:51 +02:00
( [ $other :tt $( $modifiers :tt ) * ] ) = > {
is_anon! ( [ $( $modifiers ) * ] )
2020-03-19 14:24:21 +01:00
} ;
}
macro_rules ! is_eval_always {
( [ ] ) = > { {
false
} } ;
2021-05-30 16:45:51 +02:00
( [ ( eval_always ) $( $rest :tt ) * ] ) = > { {
2020-03-19 14:24:21 +01:00
true
} } ;
2021-05-30 16:45:51 +02:00
( [ $other :tt $( $modifiers :tt ) * ] ) = > {
is_eval_always! ( [ $( $modifiers ) * ] )
2020-03-19 14:24:21 +01:00
} ;
}
2022-08-24 09:42:12 +08:00
macro_rules ! depth_limit {
( [ ] ) = > { {
false
} } ;
( [ ( depth_limit ) $( $rest :tt ) * ] ) = > { {
true
} } ;
( [ $other :tt $( $modifiers :tt ) * ] ) = > {
depth_limit! ( [ $( $modifiers ) * ] )
} ;
}
2020-03-19 14:24:21 +01:00
macro_rules ! hash_result {
2021-10-16 22:31:48 +02:00
( [ ] ) = > { {
Some ( dep_graph ::hash_result )
2020-03-19 14:24:21 +01:00
} } ;
2021-10-16 22:31:48 +02:00
( [ ( no_hash ) $( $rest :tt ) * ] ) = > { {
2020-03-19 14:24:21 +01:00
None
} } ;
2021-10-16 22:31:48 +02:00
( [ $other :tt $( $modifiers :tt ) * ] ) = > {
hash_result! ( [ $( $modifiers ) * ] )
2020-03-19 14:24:21 +01:00
} ;
}
2021-05-30 17:24:54 +02:00
macro_rules ! get_provider {
( [ ] [ $tcx :expr , $name :ident , $key :expr ] ) = > { {
$tcx . queries . local_providers . $name
} } ;
( [ ( separate_provide_extern ) $( $rest :tt ) * ] [ $tcx :expr , $name :ident , $key :expr ] ) = > { {
if $key . query_crate_is_local ( ) {
$tcx . queries . local_providers . $name
} else {
$tcx . queries . extern_providers . $name
}
} } ;
( [ $other :tt $( $modifiers :tt ) * ] [ $( $args :tt ) * ] ) = > {
get_provider! ( [ $( $modifiers ) * ] [ $( $args ) * ] )
} ;
}
2022-08-11 20:36:13 -05:00
pub ( crate ) fn create_query_frame <
' tcx ,
K : Copy + Key + for < ' a > HashStable < StableHashingContext < ' a > > ,
> (
tcx : QueryCtxt < ' tcx > ,
do_describe : fn ( QueryCtxt < ' tcx > , K ) -> String ,
key : K ,
kind : DepKind ,
name : & 'static str ,
) -> QueryStackFrame {
// Disable visible paths printing for performance reasons.
// Showing visible path instead of any path is not that important in production.
let description = ty ::print ::with_no_visible_paths! (
// Force filename-line mode to avoid invoking `type_of` query.
ty ::print ::with_forced_impl_filename_line! ( do_describe ( tcx , key ) )
) ;
let description =
if tcx . sess . verbose ( ) { format! ( " {} [ {} ] " , description , name ) } else { description } ;
let span = if kind = = dep_graph ::DepKind ::def_span {
// The `def_span` query is used to calculate `default_span`,
// so exit to avoid infinite recursion.
None
} else {
Some ( key . default_span ( * tcx ) )
} ;
let def_kind = if kind = = dep_graph ::DepKind ::opt_def_kind {
// Try to avoid infinite recursion.
None
} else {
key . key_as_def_id ( )
. and_then ( | def_id | def_id . as_local ( ) )
. and_then ( | def_id | tcx . opt_def_kind ( def_id ) )
} ;
let hash = | | {
tcx . with_stable_hashing_context ( | mut hcx | {
let mut hasher = StableHasher ::new ( ) ;
std ::mem ::discriminant ( & kind ) . hash_stable ( & mut hcx , & mut hasher ) ;
key . hash_stable ( & mut hcx , & mut hasher ) ;
hasher . finish ::< u64 > ( )
} )
} ;
QueryStackFrame ::new ( name , description , span , def_kind , hash )
}
2022-08-23 23:34:23 -05:00
pub ( crate ) fn try_load_from_on_disk_cache < ' tcx , Q , V > (
2022-08-23 22:10:47 -05:00
tcx : TyCtxt < ' tcx > ,
dep_node : DepNode ,
2022-08-23 23:34:23 -05:00
cache_query_deps : fn ( TyCtxt < ' tcx > , Q ::Key ) -> V ,
) where
Q : QueryDescription < QueryCtxt < ' tcx > > ,
Q ::Key : DepNodeParams < TyCtxt < ' tcx > > ,
{
2022-08-23 22:10:47 -05:00
debug_assert! ( tcx . dep_graph . is_green ( & dep_node ) ) ;
2022-08-23 23:34:23 -05:00
let key = Q ::Key ::recover ( tcx , & dep_node ) . unwrap_or_else ( | | {
2022-08-23 22:10:47 -05:00
panic! ( " Failed to recover key for {:?} with hash {} " , dep_node , dep_node . hash )
} ) ;
2022-08-23 23:34:23 -05:00
if Q ::cache_on_disk ( tcx , & key ) {
2022-08-23 23:31:12 -05:00
let _ = cache_query_deps ( tcx , key ) ;
2022-08-23 22:10:47 -05:00
}
}
2022-08-23 23:31:12 -05:00
pub ( crate ) fn force_from_dep_node < ' tcx , Q > ( tcx : TyCtxt < ' tcx > , dep_node : DepNode ) -> bool
2022-08-23 22:24:39 -05:00
where
Q : QueryDescription < QueryCtxt < ' tcx > > ,
Q ::Key : DepNodeParams < TyCtxt < ' tcx > > ,
{
2022-08-23 22:49:20 -05:00
if let Some ( key ) = Q ::Key ::recover ( tcx , & dep_node ) {
2022-08-23 22:24:39 -05:00
#[ cfg(debug_assertions) ]
let _guard = tracing ::span! ( tracing ::Level ::TRACE , stringify! ( $name ) , ? key ) . entered ( ) ;
let tcx = QueryCtxt ::from_tcx ( tcx ) ;
force_query ::< Q , _ > ( tcx , key , dep_node ) ;
true
} else {
false
}
}
2022-08-23 23:31:12 -05:00
pub ( crate ) fn query_callback < ' tcx , Q : QueryConfig > (
// NOTE: we can't remove these function pointers, because `recover` is invariant -> `try_load_from_on_disk_cache` takes a concrete lifetime, not a universal lifetime.
// Instead, we infer the correct lifetime at the callsite, so we can pass in a HRTB function pointer to the DepKindStruct.
try_load_from_on_disk_cache : fn ( TyCtxt < '_ > , DepNode ) ,
force_from_dep_node : fn ( TyCtxt < '_ > , DepNode ) -> bool ,
is_anon : bool ,
is_eval_always : bool ,
) -> DepKindStruct
where
Q : QueryDescription < QueryCtxt < ' tcx > > ,
Q ::Key : DepNodeParams < TyCtxt < ' tcx > > ,
{
let fingerprint_style = Q ::Key ::fingerprint_style ( ) ;
if is_anon | | ! fingerprint_style . reconstructible ( ) {
return DepKindStruct {
is_anon ,
is_eval_always ,
fingerprint_style ,
force_from_dep_node : None ,
try_load_from_on_disk_cache : None ,
} ;
}
DepKindStruct {
is_anon ,
is_eval_always ,
fingerprint_style ,
force_from_dep_node : Some ( force_from_dep_node ) ,
try_load_from_on_disk_cache : Some ( try_load_from_on_disk_cache ) ,
}
}
2022-08-11 20:36:13 -05:00
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_query_append`.
2020-10-11 20:44:24 +02:00
macro_rules ! define_queries {
2022-08-11 19:54:42 -05:00
(
2020-10-11 20:44:24 +02:00
$( $( #[ $attr:meta ] ) *
2020-10-11 20:46:46 +02:00
[ $( $modifiers :tt ) * ] fn $name :ident ( $( $K :tt ) * ) -> $V :ty , ) * ) = > {
2020-03-19 14:24:21 +01:00
define_queries_struct! {
input : ( $( ( [ $( $modifiers ) * ] [ $( $attr ) * ] [ $name ] ) ) * )
}
2020-07-05 22:58:46 +03:00
#[ allow(nonstandard_style) ]
2022-02-08 00:13:31 +03:00
mod queries {
2020-03-19 14:24:21 +01:00
use std ::marker ::PhantomData ;
2022-08-11 19:54:42 -05:00
$( pub struct $name < ' tcx > {
data : PhantomData < & ' tcx ( ) >
2020-03-19 14:24:21 +01:00
} ) *
}
2022-08-11 19:54:42 -05:00
$( impl < ' tcx > QueryConfig for queries ::$name < ' tcx > {
type Key = query_keys ::$name < ' tcx > ;
type Value = query_values ::$name < ' tcx > ;
type Stored = query_stored ::$name < ' tcx > ;
2020-03-19 14:24:21 +01:00
const NAME : & 'static str = stringify! ( $name ) ;
}
2022-08-11 19:54:42 -05:00
impl < ' tcx > QueryDescription < QueryCtxt < ' tcx > > for queries ::$name < ' tcx > {
2022-08-24 00:22:27 -05:00
rustc_query_description! { $name }
2020-03-19 14:24:21 +01:00
2022-08-11 19:54:42 -05:00
type Cache = query_storage ::$name < ' tcx > ;
2020-03-19 14:24:21 +01:00
#[ inline(always) ]
2022-08-11 19:54:42 -05:00
fn query_state < ' a > ( tcx : QueryCtxt < ' tcx > ) -> & ' a QueryState < Self ::Key >
where QueryCtxt < ' tcx > : ' a
2020-12-26 16:36:55 +01:00
{
2020-03-19 14:24:21 +01:00
& tcx . queries . $name
}
2021-02-06 13:49:08 +01:00
#[ inline(always) ]
2022-08-11 19:54:42 -05:00
fn query_cache < ' a > ( tcx : QueryCtxt < ' tcx > ) -> & ' a Self ::Cache
2021-02-06 13:49:08 +01:00
where ' tcx :' a
{
& tcx . query_caches . $name
}
2020-03-19 14:24:21 +01:00
#[ inline ]
2021-10-17 17:37:20 +02:00
fn make_vtable ( tcx : QueryCtxt < ' tcx > , key : & Self ::Key ) ->
2022-08-11 19:54:42 -05:00
QueryVTable < QueryCtxt < ' tcx > , Self ::Key , Self ::Value >
2021-05-10 19:09:30 +02:00
{
2021-05-30 17:24:54 +02:00
let compute = get_provider! ( [ $( $modifiers ) * ] [ tcx , $name , key ] ) ;
2021-10-23 18:12:43 +02:00
let cache_on_disk = Self ::cache_on_disk ( tcx . tcx , key ) ;
2022-07-19 19:57:44 -04:00
QueryVTable {
2021-10-17 17:37:20 +02:00
anon : is_anon ! ( [ $( $modifiers ) * ] ) ,
eval_always : is_eval_always ! ( [ $( $modifiers ) * ] ) ,
2022-08-24 09:42:12 +08:00
depth_limit : depth_limit ! ( [ $( $modifiers ) * ] ) ,
2021-10-17 17:37:20 +02:00
dep_kind : dep_graph ::DepKind ::$name ,
hash_result : hash_result ! ( [ $( $modifiers ) * ] ) ,
handle_cycle_error : | tcx , mut error | handle_cycle_error! ( [ $( $modifiers ) * ] [ tcx , error ] ) ,
compute ,
cache_on_disk ,
try_load_from_disk : Self ::TRY_LOAD_FROM_DISK ,
2021-05-10 19:09:30 +02:00
}
2020-03-19 14:24:21 +01:00
}
} ) *
2021-10-16 21:12:34 +02:00
#[ allow(nonstandard_style) ]
2022-02-08 00:13:31 +03:00
mod query_callbacks {
2021-01-19 19:07:06 +01:00
use super ::* ;
2021-10-02 12:06:42 -04:00
use rustc_query_system ::dep_graph ::FingerprintStyle ;
2021-01-19 19:07:06 +01:00
// We use this for most things when incr. comp. is turned off.
2021-10-16 21:12:34 +02:00
pub fn Null ( ) -> DepKindStruct {
DepKindStruct {
is_anon : false ,
is_eval_always : false ,
fingerprint_style : FingerprintStyle ::Unit ,
force_from_dep_node : Some ( | _ , dep_node | bug! ( " force_from_dep_node: encountered {:?} " , dep_node ) ) ,
try_load_from_on_disk_cache : None ,
}
}
2021-10-16 20:10:23 +02:00
2022-05-03 22:04:49 +02:00
// We use this for the forever-red node.
pub fn Red ( ) -> DepKindStruct {
DepKindStruct {
is_anon : false ,
is_eval_always : false ,
fingerprint_style : FingerprintStyle ::Unit ,
force_from_dep_node : Some ( | _ , dep_node | bug! ( " force_from_dep_node: encountered {:?} " , dep_node ) ) ,
try_load_from_on_disk_cache : None ,
}
}
2021-10-16 21:12:34 +02:00
pub fn TraitSelect ( ) -> DepKindStruct {
DepKindStruct {
is_anon : true ,
is_eval_always : false ,
fingerprint_style : FingerprintStyle ::Unit ,
force_from_dep_node : None ,
try_load_from_on_disk_cache : None ,
}
}
2021-01-19 19:07:06 +01:00
2021-10-16 21:12:34 +02:00
pub fn CompileCodegenUnit ( ) -> DepKindStruct {
DepKindStruct {
is_anon : false ,
is_eval_always : false ,
fingerprint_style : FingerprintStyle ::Opaque ,
force_from_dep_node : None ,
try_load_from_on_disk_cache : None ,
}
}
2021-10-16 20:10:23 +02:00
2021-10-16 21:12:34 +02:00
pub fn CompileMonoItem ( ) -> DepKindStruct {
DepKindStruct {
is_anon : false ,
is_eval_always : false ,
fingerprint_style : FingerprintStyle ::Opaque ,
force_from_dep_node : None ,
try_load_from_on_disk_cache : None ,
}
}
2021-01-19 19:07:06 +01:00
2022-02-07 22:45:29 +03:00
$( pub ( crate ) fn $name ( ) -> DepKindStruct {
2021-10-16 21:12:34 +02:00
let is_anon = is_anon! ( [ $( $modifiers ) * ] ) ;
let is_eval_always = is_eval_always! ( [ $( $modifiers ) * ] ) ;
2022-08-23 23:31:12 -05:00
type Q < ' tcx > = queries ::$name < ' tcx > ;
2021-10-16 20:10:23 +02:00
2022-08-23 23:31:12 -05:00
$crate ::plumbing ::query_callback ::< Q < '_ > > (
2022-08-23 23:34:23 -05:00
| tcx , key | $crate ::plumbing ::try_load_from_on_disk_cache ::< Q < '_ > , _ > ( tcx , key , TyCtxt ::$name ) ,
2022-08-23 23:31:12 -05:00
| tcx , key | $crate ::plumbing ::force_from_dep_node ::< Q < '_ > > ( tcx , key ) ,
2021-10-16 20:10:23 +02:00
is_anon ,
2022-08-23 23:31:12 -05:00
is_eval_always
)
2021-10-16 21:12:34 +02:00
} ) *
2021-01-19 19:07:06 +01:00
}
2021-10-16 21:12:34 +02:00
pub fn query_callbacks < ' tcx > ( arena : & ' tcx Arena < ' tcx > ) -> & ' tcx [ DepKindStruct ] {
arena . alloc_from_iter ( make_dep_kind_array! ( query_callbacks ) )
}
2020-03-19 14:24:21 +01:00
}
}
macro_rules ! define_queries_struct {
2022-08-11 19:54:42 -05:00
(
2020-03-19 14:24:21 +01:00
input : ( $( ( [ $( $modifiers :tt ) * ] [ $( $attr :tt ) * ] [ $name :ident ] ) ) * ) ) = > {
2022-08-11 19:54:42 -05:00
pub struct Queries < ' tcx > {
2021-03-29 18:03:07 +02:00
local_providers : Box < Providers > ,
2021-05-30 17:24:54 +02:00
extern_providers : Box < ExternProviders > ,
2020-03-19 14:24:21 +01:00
2022-08-11 19:54:42 -05:00
pub on_disk_cache : Option < OnDiskCache < ' tcx > > ,
2021-06-28 21:12:01 +02:00
2022-02-07 11:03:51 -05:00
jobs : AtomicU64 ,
2022-08-11 20:20:46 -05:00
$( $( #[ $attr ] ) * $name : QueryState < < queries ::$name < ' tcx > as QueryConfig > ::Key > , ) *
2020-03-19 14:24:21 +01:00
}
2022-08-11 19:54:42 -05:00
impl < ' tcx > Queries < ' tcx > {
2020-10-11 10:34:13 +02:00
pub fn new (
2021-03-29 18:03:07 +02:00
local_providers : Providers ,
2021-05-30 17:24:54 +02:00
extern_providers : ExternProviders ,
2022-08-11 19:54:42 -05:00
on_disk_cache : Option < OnDiskCache < ' tcx > > ,
2020-03-19 14:24:21 +01:00
) -> Self {
Queries {
2021-03-29 18:03:07 +02:00
local_providers : Box ::new ( local_providers ) ,
extern_providers : Box ::new ( extern_providers ) ,
2021-06-28 21:12:01 +02:00
on_disk_cache ,
2022-02-07 11:03:51 -05:00
jobs : AtomicU64 ::new ( 1 ) ,
2020-03-19 14:24:21 +01:00
$( $name : Default ::default ( ) ) , *
}
}
pub ( crate ) fn try_collect_active_jobs (
2022-08-11 19:54:42 -05:00
& ' tcx self ,
tcx : TyCtxt < ' tcx > ,
2022-02-07 11:03:51 -05:00
) -> Option < QueryMap > {
2020-12-26 16:36:55 +01:00
let tcx = QueryCtxt { tcx , queries : self } ;
2020-11-28 22:48:05 +01:00
let mut jobs = QueryMap ::default ( ) ;
2020-03-19 14:24:21 +01:00
$(
2022-08-23 21:47:59 -05:00
let make_query = | tcx , key | {
let kind = dep_graph ::DepKind ::$name ;
let name = stringify! ( $name ) ;
$crate ::plumbing ::create_query_frame ( tcx , queries ::$name ::describe , key , kind , name )
} ;
2020-03-19 14:24:21 +01:00
self . $name . try_collect_active_jobs (
2020-12-26 16:36:55 +01:00
tcx ,
2022-08-23 21:47:59 -05:00
make_query ,
2020-03-19 14:24:21 +01:00
& mut jobs ,
) ? ;
) *
Some ( jobs )
}
2021-01-18 22:32:20 +01:00
}
2021-01-17 14:58:34 +01:00
2021-12-14 12:13:07 -05:00
impl < ' tcx > QueryEngine < ' tcx > for Queries < ' tcx > {
2021-06-28 21:12:01 +02:00
fn as_any ( & ' tcx self ) -> & ' tcx dyn std ::any ::Any {
let this = unsafe { std ::mem ::transmute ::< & Queries < '_ > , & Queries < '_ > > ( self ) } ;
this as _
}
2021-01-18 22:32:20 +01:00
fn try_mark_green ( & ' tcx self , tcx : TyCtxt < ' tcx > , dep_node : & dep_graph ::DepNode ) -> bool {
let qcx = QueryCtxt { tcx , queries : self } ;
tcx . dep_graph . try_mark_green ( qcx , dep_node ) . is_some ( )
}
2021-01-17 14:58:34 +01:00
$( $( #[ $attr ] ) *
#[ inline(always) ]
2022-06-28 15:18:07 +00:00
#[ tracing::instrument(level = " trace " , skip(self, tcx), ret) ]
2021-01-17 14:58:34 +01:00
fn $name (
2020-10-11 10:34:13 +02:00
& ' tcx self ,
2022-08-11 19:54:42 -05:00
tcx : TyCtxt < ' tcx > ,
2021-01-17 14:58:34 +01:00
span : Span ,
2022-08-11 20:20:46 -05:00
key : < queries ::$name < ' tcx > as QueryConfig > ::Key ,
2021-01-17 14:58:34 +01:00
mode : QueryMode ,
2022-08-11 19:54:42 -05:00
) -> Option < query_stored ::$name < ' tcx > > {
2020-10-11 10:34:13 +02:00
let qcx = QueryCtxt { tcx , queries : self } ;
2022-08-11 19:54:42 -05:00
get_query ::< queries ::$name < ' tcx > , _ > ( qcx , span , key , mode )
2021-01-17 14:58:34 +01:00
} ) *
2020-03-19 14:24:21 +01:00
}
} ;
}