@@ -488,20 +488,70 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
488
488
}
489
489
}
490
490
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 ) ,
502
553
}
503
- None => Ok ( EvaluatedToAmbig ) ,
504
- } ,
554
+ }
505
555
506
556
ty:: PredicateKind :: TypeOutlives ( pred) => {
507
557
// A global type with no late-bound regions can only
@@ -718,6 +768,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
718
768
719
769
debug ! ( ?fresh_trait_pred) ;
720
770
771
+ // If a trait predicate is in the (local or global) evaluation cache,
772
+ // then we know it holds without cycles.
721
773
if let Some ( result) = self . check_evaluation_cache ( param_env, fresh_trait_pred) {
722
774
debug ! ( ?result, "CACHE HIT" ) ;
723
775
return Ok ( result) ;
@@ -921,7 +973,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
921
973
/// - it also appears in the backtrace at some position `X`,
922
974
/// - all the predicates at positions `X..` between `X` and the top are
923
975
/// 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
925
977
where
926
978
I : Iterator < Item = ty:: Predicate < ' tcx > > ,
927
979
{
@@ -931,6 +983,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
931
983
fn coinductive_predicate ( & self , predicate : ty:: Predicate < ' tcx > ) -> bool {
932
984
let result = match predicate. kind ( ) . skip_binder ( ) {
933
985
ty:: PredicateKind :: Trait ( ref data) => self . tcx ( ) . trait_is_auto ( data. def_id ( ) ) ,
986
+ ty:: PredicateKind :: WellFormed ( _) => true ,
934
987
_ => false ,
935
988
} ;
936
989
debug ! ( ?predicate, ?result, "coinductive_predicate" ) ;
@@ -2411,6 +2464,8 @@ struct ProvisionalEvaluationCache<'tcx> {
2411
2464
/// all cache values whose DFN is >= 4 -- in this case, that
2412
2465
/// means the cached value for `F`.
2413
2466
map : RefCell < FxHashMap < ty:: PolyTraitPredicate < ' tcx > , ProvisionalEvaluation > > ,
2467
+
2468
+ wf_tys : RefCell < Vec < ( ty:: GenericArg < ' tcx > , usize ) > > ,
2414
2469
}
2415
2470
2416
2471
/// A cache value for the provisional cache: contains the depth-first
@@ -2424,7 +2479,7 @@ struct ProvisionalEvaluation {
2424
2479
2425
2480
impl < ' tcx > Default for ProvisionalEvaluationCache < ' tcx > {
2426
2481
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 ( ) }
2428
2483
}
2429
2484
}
2430
2485
0 commit comments