@@ -209,27 +209,6 @@ fn connected_to_root<'tcx>(
209209 visit_waiters ( job_map, query, |_, successor| connected_to_root ( job_map, successor, visited) )
210210}
211211
212- // Deterministically pick an query from a list
213- fn pick_query < ' a , ' tcx , T , F > ( job_map : & QueryJobMap < ' tcx > , queries : & ' a [ T ] , f : F ) -> & ' a T
214- where
215- F : Fn ( & T ) -> ( Span , QueryJobId ) ,
216- {
217- // Deterministically pick an entry point
218- // FIXME: Sort this instead
219- queries
220- . iter ( )
221- . min_by_key ( |v| {
222- let ( span, query) = f ( v) ;
223- let hash = job_map. frame_of ( query) . hash ;
224- // Prefer entry points which have valid spans for nicer error messages
225- // We add an integer to the tuple ensuring that entry points
226- // with valid spans are picked first
227- let span_cmp = if span == DUMMY_SP { 1 } else { 0 } ;
228- ( span_cmp, hash)
229- } )
230- . unwrap ( )
231- }
232-
233212/// Looks for query cycles starting from the last query in `jobs`.
234213/// If a cycle is found, all queries in the cycle is removed from `jobs` and
235214/// the function return true.
@@ -263,48 +242,56 @@ fn remove_cycle<'tcx>(
263242 }
264243 }
265244
245+ struct EntryPoint {
246+ query_in_cycle : QueryJobId ,
247+ waiter : Option < ( Span , QueryJobId ) > ,
248+ }
249+
266250 // Find the queries in the cycle which are
267251 // connected to queries outside the cycle
268252 let entry_points = stack
269253 . iter ( )
270- . filter_map ( |& ( span , query ) | {
271- if job_map. parent_of ( query ) . is_none ( ) {
254+ . filter_map ( |& ( _ , query_in_cycle ) | {
255+ if job_map. parent_of ( query_in_cycle ) . is_none ( ) {
272256 // This query is connected to the root (it has no query parent)
273- Some ( ( span , query , None ) )
257+ Some ( EntryPoint { query_in_cycle , waiter : None } )
274258 } else {
275- let mut waiters = Vec :: new ( ) ;
276- // Find all the direct waiters who lead to the root
277- let _ = visit_waiters ( job_map, query , |span, waiter| {
259+ let mut waiter_on_cycle = None ;
260+ // Find a direct waiter who leads to the root
261+ let _ = visit_waiters ( job_map, query_in_cycle , |span, waiter| {
278262 // Mark all the other queries in the cycle as already visited
279263 let mut visited = FxHashSet :: from_iter ( stack. iter ( ) . map ( |q| q. 1 ) ) ;
280264
281265 if connected_to_root ( job_map, waiter, & mut visited) . is_break ( ) {
282- waiters. push ( ( span, waiter) ) ;
266+ waiter_on_cycle = Some ( ( span, waiter) ) ;
267+ ControlFlow :: Break ( None )
268+ } else {
269+ ControlFlow :: Continue ( ( ) )
283270 }
284-
285- ControlFlow :: Continue ( ( ) )
286271 } ) ;
287- if waiters. is_empty ( ) {
288- None
289- } else {
290- // Deterministically pick one of the waiters to show to the user
291- let waiter = * pick_query ( job_map, & waiters, |s| * s) ;
292- Some ( ( span, query, Some ( waiter) ) )
293- }
272+
273+ waiter_on_cycle. map ( |waiter_on_cycle| EntryPoint {
274+ query_in_cycle,
275+ waiter : Some ( waiter_on_cycle) ,
276+ } )
294277 }
295278 } )
296- . collect :: < Vec < ( Span , QueryJobId , Option < ( Span , QueryJobId ) > ) > > ( ) ;
279+ . collect :: < Vec < EntryPoint > > ( ) ;
297280
298- // Deterministically pick an entry point
299- let ( _, entry_point, usage) = pick_query ( job_map, & entry_points, |e| ( e. 0 , e. 1 ) ) ;
281+ // Pick an entry point, preferring ones with waiters
282+ let entry_point = entry_points
283+ . iter ( )
284+ . find ( |entry_point| entry_point. waiter . is_some ( ) )
285+ . unwrap_or ( & entry_points[ 0 ] ) ;
300286
301287 // Shift the stack so that our entry point is first
302- let entry_point_pos = stack. iter ( ) . position ( |( _, query) | query == entry_point) ;
288+ let entry_point_pos =
289+ stack. iter ( ) . position ( |( _, query) | * query == entry_point. query_in_cycle ) ;
303290 if let Some ( pos) = entry_point_pos {
304291 stack. rotate_left ( pos) ;
305292 }
306293
307- let usage = usage . map ( |( span, job) | ( span, job_map. frame_of ( job) . clone ( ) ) ) ;
294+ let usage = entry_point . waiter . map ( |( span, job) | ( span, job_map. frame_of ( job) . clone ( ) ) ) ;
308295
309296 // Create the cycle error
310297 let error = CycleError {
0 commit comments