11use std:: hash:: Hash ;
22use std:: mem;
33
4- use rustc_data_structures:: hash_table:: { Entry , HashTable } ;
4+ use rustc_data_structures:: hash_table:: Entry ;
55use rustc_data_structures:: stack:: ensure_sufficient_stack;
66use rustc_data_structures:: sync:: { DynSend , DynSync } ;
77use rustc_data_structures:: { outline, sharded, sync} ;
@@ -19,7 +19,9 @@ use rustc_span::{DUMMY_SP, Span};
1919use crate :: collect_active_jobs_from_all_queries;
2020use crate :: dep_graph:: { DepNode , DepNodeIndex } ;
2121use crate :: job:: { QueryJobInfo , QueryJobMap , find_cycle_in_stack, report_cycle} ;
22- use crate :: plumbing:: { current_query_job, next_job_id, start_query} ;
22+ use crate :: plumbing:: {
23+ create_deferred_query_stack_frame, current_query_job, next_job_id, start_query,
24+ } ;
2325
2426#[ inline]
2527fn equivalent_key < K : Eq , V > ( k : K ) -> impl Fn ( & ( K , V ) ) -> bool {
@@ -42,6 +44,8 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool {
4244}
4345
4446/// Internal plumbing for collecting the set of active jobs for this query.
47+ /// Returns `false` if we failed to collect all jobs, which can happen if some
48+ /// query cache shards could not be locked.
4549///
4650/// Should only be called from `collect_active_jobs_from_all_queries`.
4751///
@@ -51,57 +55,36 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool {
5155pub ( crate ) fn gather_active_jobs < ' tcx , C > (
5256 query : & ' tcx QueryVTable < ' tcx , C > ,
5357 tcx : TyCtxt < ' tcx > ,
54- require_complete : bool ,
5558 job_map_out : & mut QueryJobMap < ' tcx > , // Out-param; job info is gathered into this map
56- ) -> Option < ( ) >
59+ ) -> bool
5760where
5861 C : QueryCache < Key : QueryKey + DynSend + DynSync > ,
5962 QueryVTable < ' tcx , C > : DynSync ,
6063{
61- let mut active = Vec :: new ( ) ;
62-
63- // Helper to gather active jobs from a single shard.
64- let mut gather_shard_jobs = |shard : & HashTable < ( C :: Key , ActiveKeyStatus < ' tcx > ) > | {
65- for ( k, v) in shard. iter ( ) {
66- if let ActiveKeyStatus :: Started ( ref job) = * v {
67- active. push ( ( * k, job. clone ( ) ) ) ;
68- }
69- }
70- } ;
71-
72- // Lock shards and gather jobs from each shard.
73- if require_complete {
74- for shard in query. state . active . lock_shards ( ) {
75- gather_shard_jobs ( & shard) ;
76- }
77- } else {
78- // We use try_lock_shards here since we are called from the
79- // deadlock handler, and this shouldn't be locked.
80- for shard in query. state . active . try_lock_shards ( ) {
81- // This can be called during unwinding, and the function has a `try_`-prefix, so
82- // don't `unwrap()` here, just manually check for `None` and do best-effort error
83- // reporting.
84- match shard {
85- None => {
86- tracing:: warn!(
87- "Failed to collect active jobs for query with name `{}`!" ,
88- query. name
89- ) ;
90- return None ;
64+ let mut ok = true ;
65+
66+ for shard in query. state . active . try_lock_shards ( ) {
67+ match shard {
68+ Some ( shard) => {
69+ for ( key, status) in shard. iter ( ) {
70+ if let ActiveKeyStatus :: Started ( job) = status {
71+ // This function to call with query state locked because it is very simple.
72+ let frame = create_deferred_query_stack_frame ( tcx, query, * key) ;
73+ job_map_out. insert ( job. id , QueryJobInfo { frame, job : job. clone ( ) } ) ;
74+ }
9175 }
92- Some ( shard) => gather_shard_jobs ( & shard) ,
76+ }
77+ None => {
78+ tracing:: warn!(
79+ "Failed to collect active jobs for query with name `{}`!" ,
80+ query. name
81+ ) ;
82+ ok = false ;
9383 }
9484 }
9585 }
9686
97- // Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call
98- // queries leading to a deadlock.
99- for ( key, job) in active {
100- let frame = crate :: plumbing:: create_deferred_query_stack_frame ( tcx, query, key) ;
101- job_map_out. insert ( job. id , QueryJobInfo { frame, job } ) ;
102- }
103-
104- Some ( ( ) )
87+ ok
10588}
10689
10790/// Guard object representing the responsibility to execute a query job and
@@ -220,9 +203,8 @@ fn cycle_error<'tcx, C: QueryCache>(
220203) -> ( C :: Value , Option < DepNodeIndex > ) {
221204 // Ensure there was no errors collecting all active jobs.
222205 // We need the complete map to ensure we find a cycle to break.
223- let job_map = collect_active_jobs_from_all_queries ( tcx, false )
224- . ok ( )
225- . expect ( "failed to collect active queries" ) ;
206+ let ( job_map, collect_ok) = collect_active_jobs_from_all_queries ( tcx) ;
207+ assert ! ( collect_ok, "failed to collect active queries for cycle error" ) ;
226208
227209 let error = find_cycle_in_stack ( try_execute, job_map, & current_query_job ( ) , span) ;
228210 ( mk_cycle ( query, tcx, error. lift ( ) ) , None )
0 commit comments