@@ -391,60 +391,10 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
391
391
// `with_anon_task` closure.
392
392
let ( ( final_entry, result) , dep_node) =
393
393
tcx. dep_graph . with_anon_task ( tcx, dep_kinds:: TraitSelect , || {
394
- // When we encounter a coinductive cycle, we have to fetch the
395
- // result of that cycle while we are still computing it. Because
396
- // of this we continuously recompute the cycle until the result
397
- // of the previous iteration is equal to the final result, at which
398
- // point we are done.
399
394
for _ in 0 ..FIXPOINT_STEP_LIMIT {
400
- let result = prove_goal ( self , inspect) ;
401
- let stack_entry = self . pop_stack ( ) ;
402
- debug_assert_eq ! ( stack_entry. input, input) ;
403
-
404
- // If the current goal is not the root of a cycle, we are done.
405
- if stack_entry. has_been_used . is_empty ( ) {
406
- return ( stack_entry, result) ;
407
- }
408
-
409
- // If it is a cycle head, we have to keep trying to prove it until
410
- // we reach a fixpoint. We need to do so for all cycle heads,
411
- // not only for the root.
412
- //
413
- // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
414
- // for an example.
415
-
416
- // Start by clearing all provisional cache entries which depend on this
417
- // the current goal.
418
- Self :: clear_dependent_provisional_results (
419
- & mut self . provisional_cache ,
420
- self . stack . next_index ( ) ,
421
- ) ;
422
-
423
- // Check whether we reached a fixpoint, either because the final result
424
- // is equal to the provisional result of the previous iteration, or because
425
- // this was only the root of either coinductive or inductive cycles, and the
426
- // final result is equal to the initial response for that case.
427
- let reached_fixpoint = if let Some ( r) = stack_entry. provisional_result {
428
- r == result
429
- } else if stack_entry. has_been_used == HasBeenUsed :: COINDUCTIVE_CYCLE {
430
- Self :: response_no_constraints ( tcx, input, Certainty :: Yes ) == result
431
- } else if stack_entry. has_been_used == HasBeenUsed :: INDUCTIVE_CYCLE {
432
- Self :: response_no_constraints ( tcx, input, Certainty :: overflow ( false ) )
433
- == result
434
- } else {
435
- false
436
- } ;
437
-
438
- // If we did not reach a fixpoint, update the provisional result and reevaluate.
439
- if reached_fixpoint {
440
- return ( stack_entry, result) ;
441
- } else {
442
- let depth = self . stack . push ( StackEntry {
443
- has_been_used : HasBeenUsed :: empty ( ) ,
444
- provisional_result : Some ( result) ,
445
- ..stack_entry
446
- } ) ;
447
- debug_assert_eq ! ( self . provisional_cache[ & input] . stack_depth, Some ( depth) ) ;
395
+ match self . fixpoint_step_in_task ( tcx, input, inspect, & mut prove_goal) {
396
+ StepResult :: Done ( final_entry, result) => return ( final_entry, result) ,
397
+ StepResult :: HasChanged => { }
448
398
}
449
399
}
450
400
@@ -496,6 +446,79 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
496
446
497
447
result
498
448
}
449
+ }
450
+
451
+ enum StepResult < ' tcx > {
452
+ Done ( StackEntry < ' tcx > , QueryResult < ' tcx > ) ,
453
+ HasChanged ,
454
+ }
455
+
456
+ impl < ' tcx > SearchGraph < ' tcx > {
457
+ /// When we encounter a coinductive cycle, we have to fetch the
458
+ /// result of that cycle while we are still computing it. Because
459
+ /// of this we continuously recompute the cycle until the result
460
+ /// of the previous iteration is equal to the final result, at which
461
+ /// point we are done.
462
+ fn fixpoint_step_in_task < F > (
463
+ & mut self ,
464
+ tcx : TyCtxt < ' tcx > ,
465
+ input : CanonicalInput < ' tcx > ,
466
+ inspect : & mut ProofTreeBuilder < TyCtxt < ' tcx > > ,
467
+ prove_goal : & mut F ,
468
+ ) -> StepResult < ' tcx >
469
+ where
470
+ F : FnMut ( & mut Self , & mut ProofTreeBuilder < TyCtxt < ' tcx > > ) -> QueryResult < ' tcx > ,
471
+ {
472
+ let result = prove_goal ( self , inspect) ;
473
+ let stack_entry = self . pop_stack ( ) ;
474
+ debug_assert_eq ! ( stack_entry. input, input) ;
475
+
476
+ // If the current goal is not the root of a cycle, we are done.
477
+ if stack_entry. has_been_used . is_empty ( ) {
478
+ return StepResult :: Done ( stack_entry, result) ;
479
+ }
480
+
481
+ // If it is a cycle head, we have to keep trying to prove it until
482
+ // we reach a fixpoint. We need to do so for all cycle heads,
483
+ // not only for the root.
484
+ //
485
+ // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
486
+ // for an example.
487
+
488
+ // Start by clearing all provisional cache entries which depend on this
489
+ // the current goal.
490
+ Self :: clear_dependent_provisional_results (
491
+ & mut self . provisional_cache ,
492
+ self . stack . next_index ( ) ,
493
+ ) ;
494
+
495
+ // Check whether we reached a fixpoint, either because the final result
496
+ // is equal to the provisional result of the previous iteration, or because
497
+ // this was only the root of either coinductive or inductive cycles, and the
498
+ // final result is equal to the initial response for that case.
499
+ let reached_fixpoint = if let Some ( r) = stack_entry. provisional_result {
500
+ r == result
501
+ } else if stack_entry. has_been_used == HasBeenUsed :: COINDUCTIVE_CYCLE {
502
+ Self :: response_no_constraints ( tcx, input, Certainty :: Yes ) == result
503
+ } else if stack_entry. has_been_used == HasBeenUsed :: INDUCTIVE_CYCLE {
504
+ Self :: response_no_constraints ( tcx, input, Certainty :: overflow ( false ) ) == result
505
+ } else {
506
+ false
507
+ } ;
508
+
509
+ // If we did not reach a fixpoint, update the provisional result and reevaluate.
510
+ if reached_fixpoint {
511
+ StepResult :: Done ( stack_entry, result)
512
+ } else {
513
+ let depth = self . stack . push ( StackEntry {
514
+ has_been_used : HasBeenUsed :: empty ( ) ,
515
+ provisional_result : Some ( result) ,
516
+ ..stack_entry
517
+ } ) ;
518
+ debug_assert_eq ! ( self . provisional_cache[ & input] . stack_depth, Some ( depth) ) ;
519
+ StepResult :: HasChanged
520
+ }
521
+ }
499
522
500
523
fn response_no_constraints (
501
524
tcx : TyCtxt < ' tcx > ,
0 commit comments