@@ -488,20 +488,70 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
488488 }
489489 }
490490
491- ty:: PredicateKind :: WellFormed ( arg) => match wf:: obligations (
492- self . infcx ,
493- obligation. param_env ,
494- obligation. cause . body_id ,
495- obligation. recursion_depth + 1 ,
496- arg,
497- obligation. cause . span ,
498- ) {
499- Some ( mut obligations) => {
500- self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
501- self . evaluate_predicates_recursively ( previous_stack, obligations)
491+ ty:: PredicateKind :: WellFormed ( arg) => {
492+ // So, there is a bit going on here. First, `WellFormed` predicates
493+ // are coinductive, like trait predicates with auto traits.
494+ // This means that we need to detect if we have recursively
495+ // evaluated `WellFormed(X)`. Otherwise, we would run into
496+ // a "natural" overflow error.
497+ //
498+ // Now, the next question is whether we need to do anything
499+ // special with caching. Considering the following tree:
500+ // - `WF(Foo<T>)`
501+ // - `Bar<T>: Send`
502+ // - `WF(Foo<T>)`
503+ // - `Foo<T>: Trait`
504+ // In this case, the innermost `WF(Foo<T>)` should return
505+ // `EvaluatedToOk`, since it's coinductive. Then if
506+ // `Bar<T>: Send` is resolved to `EvaluatedToOk`, it can be
507+ // inserted into a cache (because without thinking about `WF`
508+ // goals, it isn't in a cycle). If `Foo<T>: Trait` later doesn't
509+ // hold, then `Bar<T>: Send` shouldn't hold. Therefore, we
510+ // *do* need to keep track of coinductive cycles.
511+
512+ let cache = previous_stack. cache ;
513+ let dfn = cache. next_dfn ( ) ;
514+
515+ for stack_arg in previous_stack. cache . wf_tys . borrow ( ) . iter ( ) . rev ( ) {
516+ if stack_arg. 0 != arg {
517+ continue ;
518+ }
519+ debug ! ( "WellFormed({:?}) on stack" , arg) ;
520+ if let Some ( stack) = previous_stack. head {
521+ stack. update_reached_depth ( stack_arg. 1 ) ;
522+ }
523+ return Ok ( EvaluatedToOk ) ;
524+ }
525+
526+ match wf:: obligations (
527+ self . infcx ,
528+ obligation. param_env ,
529+ obligation. cause . body_id ,
530+ obligation. recursion_depth + 1 ,
531+ arg,
532+ obligation. cause . span ,
533+ ) {
534+ Some ( mut obligations) => {
535+ self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
536+
537+ cache. wf_tys . borrow_mut ( ) . push ( ( arg, previous_stack. depth ( ) ) ) ;
538+ let result =
539+ self . evaluate_predicates_recursively ( previous_stack, obligations) ;
540+ cache. wf_tys . borrow_mut ( ) . pop ( ) ;
541+
542+ let result = result?;
543+
544+ if !result. must_apply_modulo_regions ( ) {
545+ cache. on_failure ( dfn) ;
546+ }
547+
548+ cache. on_completion ( dfn) ;
549+
550+ Ok ( result)
551+ }
552+ None => Ok ( EvaluatedToAmbig ) ,
502553 }
503- None => Ok ( EvaluatedToAmbig ) ,
504- } ,
554+ }
505555
506556 ty:: PredicateKind :: TypeOutlives ( pred) => {
507557 // A global type with no late-bound regions can only
@@ -718,6 +768,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
718768
719769 debug ! ( ?fresh_trait_pred) ;
720770
771+ // If a trait predicate is in the (local or global) evaluation cache,
772+ // then we know it holds without cycles.
721773 if let Some ( result) = self . check_evaluation_cache ( param_env, fresh_trait_pred) {
722774 debug ! ( ?result, "CACHE HIT" ) ;
723775 return Ok ( result) ;
@@ -921,7 +973,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
921973 /// - it also appears in the backtrace at some position `X`,
922974 /// - all the predicates at positions `X..` between `X` and the top are
923975 /// also defaulted traits.
924- pub fn coinductive_match < I > ( & mut self , mut cycle : I ) -> bool
976+ pub ( crate ) fn coinductive_match < I > ( & mut self , mut cycle : I ) -> bool
925977 where
926978 I : Iterator < Item = ty:: Predicate < ' tcx > > ,
927979 {
@@ -931,6 +983,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
931983 fn coinductive_predicate ( & self , predicate : ty:: Predicate < ' tcx > ) -> bool {
932984 let result = match predicate. kind ( ) . skip_binder ( ) {
933985 ty:: PredicateKind :: Trait ( ref data) => self . tcx ( ) . trait_is_auto ( data. def_id ( ) ) ,
986+ ty:: PredicateKind :: WellFormed ( _) => true ,
934987 _ => false ,
935988 } ;
936989 debug ! ( ?predicate, ?result, "coinductive_predicate" ) ;
@@ -2411,6 +2464,8 @@ struct ProvisionalEvaluationCache<'tcx> {
24112464 /// all cache values whose DFN is >= 4 -- in this case, that
24122465 /// means the cached value for `F`.
24132466 map : RefCell < FxHashMap < ty:: PolyTraitPredicate < ' tcx > , ProvisionalEvaluation > > ,
2467+
2468+ wf_tys : RefCell < Vec < ( ty:: GenericArg < ' tcx > , usize ) > > ,
24142469}
24152470
24162471/// A cache value for the provisional cache: contains the depth-first
@@ -2424,7 +2479,7 @@ struct ProvisionalEvaluation {
24242479
24252480impl < ' tcx > Default for ProvisionalEvaluationCache < ' tcx > {
24262481 fn default ( ) -> Self {
2427- Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) }
2482+ Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) , wf_tys : Default :: default ( ) }
24282483 }
24292484}
24302485
0 commit comments