@@ -42,7 +42,7 @@ use rustc_data_structures::bit_set::GrowableBitSet;
42
42
use rustc_data_structures:: sync:: Lock ;
43
43
use rustc_target:: spec:: abi:: Abi ;
44
44
use std:: cmp;
45
- use std:: fmt;
45
+ use std:: fmt:: { self , Display } ;
46
46
use std:: iter;
47
47
use std:: rc:: Rc ;
48
48
use util:: nodemap:: { FxHashMap , FxHashSet } ;
@@ -660,7 +660,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
660
660
{
661
661
let mut result = EvaluatedToOk ;
662
662
for obligation in predicates {
663
- let eval = self . evaluate_predicate_recursively ( stack, obligation) ?;
663
+ let eval = self . evaluate_predicate_recursively ( stack, obligation. clone ( ) ) ?;
664
664
debug ! (
665
665
"evaluate_predicate_recursively({:?}) = {:?}" ,
666
666
obligation, eval
@@ -682,13 +682,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
682
682
obligation : PredicateObligation < ' tcx > ,
683
683
) -> Result < EvaluationResult , OverflowError > {
684
684
debug ! ( "evaluate_predicate_recursively({:?})" , obligation) ;
685
- self . check_recursion_limit ( obligation) ?;
685
+ self . check_recursion_limit ( & obligation) ?;
686
686
687
687
match obligation. predicate {
688
688
ty:: Predicate :: Trait ( ref t) => {
689
689
debug_assert ! ( !t. has_escaping_bound_vars( ) ) ;
690
690
let mut obligation = obligation. with ( t. clone ( ) ) ;
691
- obligation. recursion_depth += 1
691
+ obligation. recursion_depth += 1 ;
692
692
self . evaluate_trait_predicate_recursively ( previous_stack, obligation)
693
693
}
694
694
@@ -697,11 +697,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
697
697
match self . infcx
698
698
. subtype_predicate ( & obligation. cause , obligation. param_env , p)
699
699
{
700
- Some ( Ok ( InferOk { obligations, .. } ) ) => {
701
- for o in obligations. iter_mut ( ) {
702
- o. recursion_depth += 1
703
- }
704
- self . evaluate_predicates_recursively ( previous_stack, obligation. into_iter ( ) )
700
+ Some ( Ok ( InferOk { mut obligations, .. } ) ) => {
701
+ self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
702
+ self . evaluate_predicates_recursively ( previous_stack, obligations. into_iter ( ) )
705
703
}
706
704
Some ( Err ( _) ) => Ok ( EvaluatedToErr ) ,
707
705
None => Ok ( EvaluatedToAmbig ) ,
@@ -715,11 +713,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
715
713
ty,
716
714
obligation. cause . span ,
717
715
) {
718
- Some ( obligations) => {
719
- for o in obligations. iter_mut ( ) {
720
- o. recursion_depth += 1
721
- }
722
- self . evaluate_predicates_recursively ( previous_stack, obligations. iter ( ) )
716
+ Some ( mut obligations) => {
717
+ self . add_depth ( obligations. iter_mut ( ) , obligation. recursion_depth ) ;
718
+ self . evaluate_predicates_recursively ( previous_stack, obligations. into_iter ( ) )
723
719
}
724
720
None => Ok ( EvaluatedToAmbig ) ,
725
721
} ,
@@ -741,10 +737,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
741
737
ty:: Predicate :: Projection ( ref data) => {
742
738
let project_obligation = obligation. with ( data. clone ( ) ) ;
743
739
match project:: poly_project_and_unify_type ( self , & project_obligation) {
744
- Ok ( Some ( subobligations) ) => {
745
- for o in subobligations. iter_mut ( ) {
746
- o. recursion_depth += 1
747
- }
740
+ Ok ( Some ( mut subobligations) ) => {
741
+ self . add_depth ( subobligations. iter_mut ( ) , obligation. recursion_depth ) ;
748
742
let result = self . evaluate_predicates_recursively (
749
743
previous_stack,
750
744
subobligations. into_iter ( ) ,
@@ -1016,7 +1010,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1016
1010
match this. confirm_candidate ( stack. obligation , candidate) {
1017
1011
Ok ( selection) => this. evaluate_predicates_recursively (
1018
1012
stack. list ( ) ,
1019
- selection. nested_obligations ( ) . iter ( ) ,
1013
+ selection. nested_obligations ( ) . into_iter ( ) ,
1020
1014
) ,
1021
1015
Err ( ..) => Ok ( EvaluatedToErr ) ,
1022
1016
}
@@ -1091,14 +1085,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1091
1085
. insert ( trait_ref, WithDepNode :: new ( dep_node, result) ) ;
1092
1086
}
1093
1087
1088
+ // Due to caching of projection results, it's possible for a subobligation
1089
+ // to have a *lower* recursion_depth than the obligation used to create it.
1090
+ // To ensure that obligation_depth never decreasees, we force all subobligations
1091
+ // to have at least the depth of the original obligation.
1092
+ fn add_depth < T : ' cx , I : Iterator < Item = & ' cx mut Obligation < ' tcx , T > > > ( & self , it : I ,
1093
+ min_depth : usize ) {
1094
+ it. for_each ( |o| o. recursion_depth = cmp:: max ( min_depth, o. recursion_depth ) + 1 ) ;
1095
+ }
1096
+
1094
1097
// Check that the recursion limit has not been exceeded.
1095
1098
//
1096
1099
// The weird return type of this function allows it to be used with the 'try' (?)
1097
1100
// operator within certain functions
1098
1101
fn check_recursion_limit < T : Display + TypeFoldable < ' tcx > > ( & self , obligation : & Obligation < ' tcx , T > ,
1099
1102
) -> Result < ( ) , OverflowError > {
1100
1103
let recursion_limit = * self . infcx . tcx . sess . recursion_limit . get ( ) ;
1101
- if obligaton . recursion_depth >= recursion_limit {
1104
+ if obligation . recursion_depth >= recursion_limit {
1102
1105
match self . query_mode {
1103
1106
TraitQueryMode :: Standard => {
1104
1107
self . infcx ( ) . report_overflow_error ( obligation, true ) ;
@@ -1796,7 +1799,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1796
1799
self . evaluation_probe ( |this| {
1797
1800
match this. match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
1798
1801
Ok ( obligations) => {
1799
- this. evaluate_predicates_recursively ( stack. list ( ) , obligations. iter ( ) )
1802
+ this. evaluate_predicates_recursively ( stack. list ( ) , obligations. into_iter ( ) )
1800
1803
}
1801
1804
Err ( ( ) ) => Ok ( EvaluatedToErr ) ,
1802
1805
}
0 commit comments