@@ -5,7 +5,7 @@ use rustc_data_structures::hash_table::{Entry, HashTable};
55use rustc_data_structures:: stack:: ensure_sufficient_stack;
66use rustc_data_structures:: sync:: { DynSend , DynSync } ;
77use rustc_data_structures:: { outline, sharded, sync} ;
8- use rustc_errors:: { FatalError , StashKey } ;
8+ use rustc_errors:: FatalError ;
99use rustc_middle:: dep_graph:: { DepGraphData , DepNodeKey , SerializedDepNodeIndex } ;
1010use rustc_middle:: query:: plumbing:: QueryVTable ;
1111use rustc_middle:: query:: {
@@ -16,8 +16,8 @@ use rustc_middle::ty::TyCtxt;
1616use rustc_middle:: verify_ich:: incremental_verify_ich;
1717use rustc_span:: { DUMMY_SP , Span } ;
1818
19- use crate :: collect_active_jobs_from_all_queries;
2019use crate :: dep_graph:: { DepNode , DepNodeIndex } ;
20+ use crate :: for_each_query_vtable;
2121use crate :: job:: { QueryJobInfo , QueryJobMap , find_cycle_in_stack, report_cycle} ;
2222use crate :: plumbing:: { current_query_job, next_job_id, start_query} ;
2323
@@ -30,14 +30,41 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool {
3030 state. active . lock_shards ( ) . all ( |shard| shard. is_empty ( ) )
3131}
3232
33+ /// Returns a map of currently active query jobs, collected from all queries.
34+ ///
35+ /// If `require_complete` is `true`, this function locks all shards of the
36+ /// query results to produce a complete map, which always returns `Ok`.
37+ /// Otherwise, it may return an incomplete map as an error if any shard
38+ /// lock cannot be acquired.
39+ ///
40+ /// Prefer passing `false` to `require_complete` to avoid potential deadlocks,
41+ /// especially when called from within a deadlock handler, unless a
42+ /// complete map is needed and no deadlock is possible at this call site.
43+ pub fn collect_active_jobs_from_all_queries < ' tcx > (
44+ tcx : TyCtxt < ' tcx > ,
45+ require_complete : bool ,
46+ ) -> Result < QueryJobMap < ' tcx > , QueryJobMap < ' tcx > > {
47+ let mut job_map_out = QueryJobMap :: default ( ) ;
48+ let mut complete = true ;
49+
50+ for_each_query_vtable ! ( ALL , tcx, |query| {
51+ let res = gather_active_jobs( query, tcx, require_complete, & mut job_map_out) ;
52+ if res. is_none( ) {
53+ complete = false ;
54+ }
55+ } ) ;
56+
57+ if complete { Ok ( job_map_out) } else { Err ( job_map_out) }
58+ }
59+
3360/// Internal plumbing for collecting the set of active jobs for this query.
3461///
3562/// Should only be called from `collect_active_jobs_from_all_queries`.
3663///
3764/// (We arbitrarily use the word "gather" when collecting the jobs for
3865/// each individual query, so that we have distinct function names to
3966/// grep for.)
40- pub ( crate ) fn gather_active_jobs < ' tcx , C > (
67+ fn gather_active_jobs < ' tcx , C > (
4168 query : & ' tcx QueryVTable < ' tcx , C > ,
4269 tcx : TyCtxt < ' tcx > ,
4370 require_complete : bool ,
@@ -110,16 +137,6 @@ fn mk_cycle<'tcx, C: QueryCache>(
110137 let guar = error. delay_as_bug ( ) ;
111138 ( query. value_from_cycle_error ) ( tcx, cycle_error, guar)
112139 }
113- CycleErrorHandling :: Stash => {
114- let guar = if let Some ( root) = cycle_error. cycle . first ( )
115- && let Some ( span) = root. frame . info . span
116- {
117- error. stash ( span, StashKey :: Cycle ) . unwrap ( )
118- } else {
119- error. emit ( )
120- } ;
121- ( query. value_from_cycle_error ) ( tcx, cycle_error, guar)
122- }
123140 }
124141}
125142
0 commit comments