@@ -488,20 +488,93 @@ 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_args . 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
+ // 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
+ }
545
+ }
546
+ return Ok ( EvaluatedToOk ) ;
502
547
}
503
- None => Ok ( EvaluatedToAmbig ) ,
504
- } ,
548
+
549
+ match wf:: obligations (
550
+ self . infcx ,
551
+ obligation. param_env ,
552
+ obligation. cause . body_id ,
553
+ obligation. recursion_depth + 1 ,
554
+ arg,
555
+ obligation. cause . span ,
556
+ ) {
557
+ Some ( mut obligations) => {
558
+ self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
559
+
560
+ cache. wf_args . borrow_mut ( ) . push ( ( arg, previous_stack. depth ( ) ) ) ;
561
+ let result =
562
+ self . evaluate_predicates_recursively ( previous_stack, obligations) ;
563
+ cache. wf_args . borrow_mut ( ) . pop ( ) ;
564
+
565
+ let result = result?;
566
+
567
+ if !result. must_apply_modulo_regions ( ) {
568
+ cache. on_failure ( dfn) ;
569
+ }
570
+
571
+ cache. on_completion ( dfn) ;
572
+
573
+ Ok ( result)
574
+ }
575
+ None => Ok ( EvaluatedToAmbig ) ,
576
+ }
577
+ }
505
578
506
579
ty:: PredicateKind :: TypeOutlives ( pred) => {
507
580
// A global type with no late-bound regions can only
@@ -718,6 +791,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
718
791
719
792
debug ! ( ?fresh_trait_pred) ;
720
793
794
+ // If a trait predicate is in the (local or global) evaluation cache,
795
+ // then we know it holds without cycles.
721
796
if let Some ( result) = self . check_evaluation_cache ( param_env, fresh_trait_pred) {
722
797
debug ! ( ?result, "CACHE HIT" ) ;
723
798
return Ok ( result) ;
@@ -921,7 +996,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
921
996
/// - it also appears in the backtrace at some position `X`,
922
997
/// - all the predicates at positions `X..` between `X` and the top are
923
998
/// also defaulted traits.
924
- pub fn coinductive_match < I > ( & mut self , mut cycle : I ) -> bool
999
+ pub ( crate ) fn coinductive_match < I > ( & mut self , mut cycle : I ) -> bool
925
1000
where
926
1001
I : Iterator < Item = ty:: Predicate < ' tcx > > ,
927
1002
{
@@ -931,6 +1006,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
931
1006
fn coinductive_predicate ( & self , predicate : ty:: Predicate < ' tcx > ) -> bool {
932
1007
let result = match predicate. kind ( ) . skip_binder ( ) {
933
1008
ty:: PredicateKind :: Trait ( ref data) => self . tcx ( ) . trait_is_auto ( data. def_id ( ) ) ,
1009
+ ty:: PredicateKind :: WellFormed ( _) => true ,
934
1010
_ => false ,
935
1011
} ;
936
1012
debug ! ( ?predicate, ?result, "coinductive_predicate" ) ;
@@ -2410,6 +2486,15 @@ struct ProvisionalEvaluationCache<'tcx> {
2410
2486
/// all cache values whose DFN is >= 4 -- in this case, that
2411
2487
/// means the cached value for `F`.
2412
2488
map : RefCell < FxHashMap < ty:: PolyTraitPredicate < ' tcx > , ProvisionalEvaluation > > ,
2489
+
2490
+ /// The stack of args that we assume to be true because a `WF(arg)` predicate
2491
+ /// is on the stack above (and because of wellformedness is coinductive).
2492
+ /// In an "ideal" world, this would share a stack with trait predicates in
2493
+ /// `TraitObligationStack`. However, trait predicates are *much* hotter than
2494
+ /// `WellFormed` predicates, and it's very likely that the additional matches
2495
+ /// will have a perf effect. The value here is the well-formed `GenericArg`
2496
+ /// and the depth of the trait predicate *above* that well-formed predicate.
2497
+ wf_args : RefCell < Vec < ( ty:: GenericArg < ' tcx > , usize ) > > ,
2413
2498
}
2414
2499
2415
2500
/// A cache value for the provisional cache: contains the depth-first
@@ -2423,7 +2508,7 @@ struct ProvisionalEvaluation {
2423
2508
2424
2509
impl < ' tcx > Default for ProvisionalEvaluationCache < ' tcx > {
2425
2510
fn default ( ) -> Self {
2426
- Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) }
2511
+ Self { dfn : Cell :: new ( 0 ) , map : Default :: default ( ) , wf_args : Default :: default ( ) }
2427
2512
}
2428
2513
}
2429
2514
0 commit comments