@@ -512,13 +512,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
512512 let cache = previous_stack. cache ;
513513 let dfn = cache. next_dfn ( ) ;
514514
515- for stack_arg in previous_stack. cache . wf_tys . borrow ( ) . iter ( ) . rev ( ) {
515+ for stack_arg in previous_stack. cache . wf_args . borrow ( ) . iter ( ) . rev ( ) {
516516 if stack_arg. 0 != arg {
517517 continue ;
518518 }
519519 debug ! ( "WellFormed({:?}) on stack" , arg) ;
520520 if let Some ( stack) = previous_stack. head {
521- stack. update_reached_depth ( stack_arg. 1 ) ;
521+ // Okay, let's imagine we have two different stacks:
522+ // `T: NonAutoTrait -> WF(T) -> T: NonAutoTrait`
523+ // `WF(T) -> T: NonAutoTrait -> WF(T)`
524+ // Because of this, we need to check that all
525+ // predicates between the WF goals are coinductive.
526+ // Otherwise, we can say that `T: NonAutoTrait` is
527+ // true.
528+ // Let's imagine we have a predicate stack like
529+ // `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto
530+ // depth ^1 ^2 ^3
531+ // and the current predicate is `WF(T)`. `wf_args`
532+ // would contain `(T, 1)`. We want to check all
533+ // trait predicates greater than `1`. The previous
534+ // stack would be `T: Auto`.
535+ let cycle = stack. iter ( ) . take_while ( |s| s. depth > stack_arg. 1 ) ;
536+ let tcx = self . tcx ( ) ;
537+ let cycle =
538+ cycle. map ( |stack| stack. obligation . predicate . to_predicate ( tcx) ) ;
539+ if self . coinductive_match ( cycle) {
540+ stack. update_reached_depth ( stack_arg. 1 ) ;
541+ return Ok ( EvaluatedToOk ) ;
542+ } else {
543+ return Ok ( EvaluatedToRecur ) ;
544+ }
522545 }
523546 return Ok ( EvaluatedToOk ) ;
524547 }
@@ -534,10 +557,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
534557 Some ( mut obligations) => {
535558 self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
536559
537- cache. wf_tys . borrow_mut ( ) . push ( ( arg, previous_stack. depth ( ) ) ) ;
560+ cache. wf_args . borrow_mut ( ) . push ( ( arg, previous_stack. depth ( ) ) ) ;
538561 let result =
539562 self . evaluate_predicates_recursively ( previous_stack, obligations) ;
540- cache. wf_tys . borrow_mut ( ) . pop ( ) ;
563+ cache. wf_args . borrow_mut ( ) . pop ( ) ;
541564
542565 let result = result?;
543566
@@ -2465,7 +2488,14 @@ struct ProvisionalEvaluationCache<'tcx> {
24652488 /// means the cached value for `F`.
24662489 map : RefCell < FxHashMap < ty:: PolyTraitPredicate < ' tcx > , ProvisionalEvaluation > > ,
24672490
2468- wf_tys : RefCell < Vec < ( ty:: GenericArg < ' tcx > , usize ) > > ,
2491+ /// The stack of args that we assume to be true because a `WF(arg)` predicate
2492+ /// is on the stack above (and because of wellformedness is coinductive).
2493+ /// In an "ideal" world, this would share a stack with trait predicates in
2494+ /// `TraitObligationStack`. However, trait predicates are *much* hotter than
2495+ /// `WellFormed` predicates, and it's very likely that the additional matches
2496+ /// will have a perf effect. The value here is the well-formed `GenericArg`
2497+ /// and the depth of the trait predicate *above* that well-formed predicate.
2498+ wf_args : RefCell < Vec < ( ty:: GenericArg < ' tcx > , usize ) > > ,
24692499}
24702500
24712501/// A cache value for the provisional cache: contains the depth-first
@@ -2479,7 +2509,7 @@ struct ProvisionalEvaluation {
24792509
24802510impl < ' tcx > Default for ProvisionalEvaluationCache < ' tcx > {
24812511 fn default ( ) -> Self {
2482- Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) , wf_tys : Default :: default ( ) }
2512+ Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) , wf_args : Default :: default ( ) }
24832513 }
24842514}
24852515
0 commit comments