@@ -42,7 +42,7 @@ use rustc_data_structures::bit_set::GrowableBitSet;
4242use rustc_data_structures:: sync:: Lock ;
4343use rustc_target:: spec:: abi:: Abi ;
4444use std:: cmp;
45- use std:: fmt;
45+ use std:: fmt:: { self , Display } ;
4646use std:: iter;
4747use std:: rc:: Rc ;
4848use util:: nodemap:: { FxHashMap , FxHashSet } ;
@@ -573,7 +573,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
573573
574574 let stack = self . push_stack ( TraitObligationStackList :: empty ( ) , obligation) ;
575575
576- let candidate = match self . candidate_from_obligation ( & stack) {
576+ // 'select' is an entry point into SelectionContext - we never call it recursively
577+ // from within SelectionContext. Therefore, we start our recursion depth at 0
578+ let candidate = match self . candidate_from_obligation ( & stack, 0 ) {
577579 Err ( SelectionError :: Overflow ) => {
578580 // In standard mode, overflow must have been caught and reported
579581 // earlier.
@@ -629,7 +631,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
629631 obligation : & PredicateObligation < ' tcx > ,
630632 ) -> Result < EvaluationResult , OverflowError > {
631633 self . evaluation_probe ( |this| {
632- this. evaluate_predicate_recursively ( TraitObligationStackList :: empty ( ) , obligation)
634+ // Like 'select', 'evaluate_obligation_recursively' is an entry point into
635+ // SelectionContext, so our recursion depth is 0
636+ this. evaluate_predicate_recursively ( TraitObligationStackList :: empty ( ) , obligation, 0 )
633637 } )
634638 }
635639
@@ -653,14 +657,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
653657 & mut self ,
654658 stack : TraitObligationStackList < ' o , ' tcx > ,
655659 predicates : I ,
660+ recursion_depth : usize
656661 ) -> Result < EvaluationResult , OverflowError >
657662 where
658663 I : IntoIterator < Item = & ' a PredicateObligation < ' tcx > > ,
659664 ' tcx : ' a ,
660665 {
661666 let mut result = EvaluatedToOk ;
662667 for obligation in predicates {
663- let eval = self . evaluate_predicate_recursively ( stack, obligation) ?;
668+ let eval = self . evaluate_predicate_recursively ( stack, obligation, recursion_depth ) ?;
664669 debug ! (
665670 "evaluate_predicate_recursively({:?}) = {:?}" ,
666671 obligation, eval
@@ -680,14 +685,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
680685 & mut self ,
681686 previous_stack : TraitObligationStackList < ' o , ' tcx > ,
682687 obligation : & PredicateObligation < ' tcx > ,
688+ mut recursion_depth : usize
683689 ) -> Result < EvaluationResult , OverflowError > {
684- debug ! ( "evaluate_predicate_recursively({:?})" , obligation) ;
690+ debug ! ( "evaluate_predicate_recursively({:?}, recursion_depth={:?})" , obligation,
691+ recursion_depth) ;
692+
693+ // We need to check for overflow here, since the normal
694+ // recursion check uses the obligation from the stack.
695+ // This is insufficient for two reasions:
696+ // 1. That recursion depth is only incremented when a candidate is confirmed
697+ // Since evaluation skips candidate confirmation, this will never happen
698+ // 2. It relies on the trait obligation stack. However, it's possible for overflow
699+ // to happen without involving the trait obligation stack. For example,
700+ // we might end up trying to infinitely recurse with a projection predicate,
701+ // which will never push anything onto the stack.
702+ self . check_recursion_limit ( recursion_depth, obligation) ?;
703+
704+ // Now that we know that the recursion check has passed, increment our depth
705+ recursion_depth += 1 ;
685706
686707 match obligation. predicate {
687708 ty:: Predicate :: Trait ( ref t) => {
688709 debug_assert ! ( !t. has_escaping_bound_vars( ) ) ;
689710 let obligation = obligation. with ( t. clone ( ) ) ;
690- self . evaluate_trait_predicate_recursively ( previous_stack, obligation)
711+ self . evaluate_trait_predicate_recursively ( previous_stack, obligation, recursion_depth )
691712 }
692713
693714 ty:: Predicate :: Subtype ( ref p) => {
@@ -696,7 +717,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
696717 . subtype_predicate ( & obligation. cause , obligation. param_env , p)
697718 {
698719 Some ( Ok ( InferOk { obligations, .. } ) ) => {
699- self . evaluate_predicates_recursively ( previous_stack, & obligations)
720+ self . evaluate_predicates_recursively ( previous_stack, & obligations, recursion_depth )
700721 }
701722 Some ( Err ( _) ) => Ok ( EvaluatedToErr ) ,
702723 None => Ok ( EvaluatedToAmbig ) ,
@@ -711,7 +732,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
711732 obligation. cause . span ,
712733 ) {
713734 Some ( obligations) => {
714- self . evaluate_predicates_recursively ( previous_stack, obligations. iter ( ) )
735+ self . evaluate_predicates_recursively ( previous_stack, obligations. iter ( ) , recursion_depth )
715736 }
716737 None => Ok ( EvaluatedToAmbig ) ,
717738 } ,
@@ -737,6 +758,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
737758 let result = self . evaluate_predicates_recursively (
738759 previous_stack,
739760 subobligations. iter ( ) ,
761+ recursion_depth
740762 ) ;
741763 if let Some ( key) =
742764 ProjectionCacheKey :: from_poly_projection_predicate ( self , data)
@@ -795,6 +817,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
795817 & mut self ,
796818 previous_stack : TraitObligationStackList < ' o , ' tcx > ,
797819 mut obligation : TraitObligation < ' tcx > ,
820+ recursion_depth : usize
798821 ) -> Result < EvaluationResult , OverflowError > {
799822 debug ! ( "evaluate_trait_predicate_recursively({:?})" , obligation) ;
800823
@@ -822,7 +845,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
822845 return Ok ( result) ;
823846 }
824847
825- let ( result, dep_node) = self . in_task ( |this| this. evaluate_stack ( & stack) ) ;
848+ let ( result, dep_node) = self . in_task ( |this| this. evaluate_stack ( & stack, recursion_depth ) ) ;
826849 let result = result?;
827850
828851 debug ! ( "CACHE MISS: EVAL({:?})={:?}" , fresh_trait_ref, result) ;
@@ -834,6 +857,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
834857 fn evaluate_stack < ' o > (
835858 & mut self ,
836859 stack : & TraitObligationStack < ' o , ' tcx > ,
860+ recursion_depth : usize
837861 ) -> Result < EvaluationResult , OverflowError > {
838862 // In intercrate mode, whenever any of the types are unbound,
839863 // there can always be an impl. Even if there are no impls in
@@ -874,7 +898,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
874898 // Heuristics: show the diagnostics when there are no candidates in crate.
875899 if self . intercrate_ambiguity_causes . is_some ( ) {
876900 debug ! ( "evaluate_stack: intercrate_ambiguity_causes is some" ) ;
877- if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
901+ if let Ok ( candidate_set) = self . assemble_candidates ( stack, recursion_depth ) {
878902 if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
879903 let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
880904 let self_ty = trait_ref. self_ty ( ) ;
@@ -955,8 +979,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
955979 }
956980 }
957981
958- match self . candidate_from_obligation ( stack) {
959- Ok ( Some ( c) ) => self . evaluate_candidate ( stack, & c) ,
982+ match self . candidate_from_obligation ( stack, recursion_depth ) {
983+ Ok ( Some ( c) ) => self . evaluate_candidate ( stack, & c, recursion_depth ) ,
960984 Ok ( None ) => Ok ( EvaluatedToAmbig ) ,
961985 Err ( Overflow ) => Err ( OverflowError ) ,
962986 Err ( ..) => Ok ( EvaluatedToErr ) ,
@@ -995,6 +1019,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
9951019 & mut self ,
9961020 stack : & TraitObligationStack < ' o , ' tcx > ,
9971021 candidate : & SelectionCandidate < ' tcx > ,
1022+ recursion_depth : usize
9981023 ) -> Result < EvaluationResult , OverflowError > {
9991024 debug ! (
10001025 "evaluate_candidate: depth={} candidate={:?}" ,
@@ -1006,6 +1031,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10061031 Ok ( selection) => this. evaluate_predicates_recursively (
10071032 stack. list ( ) ,
10081033 selection. nested_obligations ( ) . iter ( ) ,
1034+ recursion_depth
10091035 ) ,
10101036 Err ( ..) => Ok ( EvaluatedToErr ) ,
10111037 }
@@ -1080,6 +1106,24 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10801106 . insert ( trait_ref, WithDepNode :: new ( dep_node, result) ) ;
10811107 }
10821108
1109+ // The weird return type of this function allows it to be used with the 'try' (?)
1110+ // operator within certain functions
1111+ fn check_recursion_limit < T : Display + TypeFoldable < ' tcx > > ( & self , recursion_depth : usize , obligation : & Obligation < ' tcx , T > ,
1112+ ) -> Result < ( ) , OverflowError > {
1113+ let recursion_limit = * self . infcx . tcx . sess . recursion_limit . get ( ) ;
1114+ if recursion_depth >= recursion_limit {
1115+ match self . query_mode {
1116+ TraitQueryMode :: Standard => {
1117+ self . infcx ( ) . report_overflow_error ( obligation, true ) ;
1118+ }
1119+ TraitQueryMode :: Canonical => {
1120+ return Err ( OverflowError ) ;
1121+ }
1122+ }
1123+ }
1124+ Ok ( ( ) )
1125+ }
1126+
10831127 ///////////////////////////////////////////////////////////////////////////
10841128 // CANDIDATE ASSEMBLY
10851129 //
@@ -1093,20 +1137,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10931137 fn candidate_from_obligation < ' o > (
10941138 & mut self ,
10951139 stack : & TraitObligationStack < ' o , ' tcx > ,
1140+ recursion_depth : usize
10961141 ) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
10971142 // Watch out for overflow. This intentionally bypasses (and does
10981143 // not update) the cache.
1099- let recursion_limit = * self . infcx . tcx . sess . recursion_limit . get ( ) ;
1100- if stack. obligation . recursion_depth >= recursion_limit {
1101- match self . query_mode {
1102- TraitQueryMode :: Standard => {
1103- self . infcx ( ) . report_overflow_error ( & stack. obligation , true ) ;
1104- }
1105- TraitQueryMode :: Canonical => {
1106- return Err ( Overflow ) ;
1107- }
1108- }
1109- }
1144+ self . check_recursion_limit ( stack. obligation . recursion_depth , & stack. obligation ) ?;
11101145
11111146 // Check the cache. Note that we freshen the trait-ref
11121147 // separately rather than using `stack.fresh_trait_ref` --
@@ -1128,7 +1163,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11281163
11291164 // If no match, compute result and insert into cache.
11301165 let ( candidate, dep_node) =
1131- self . in_task ( |this| this. candidate_from_obligation_no_cache ( stack) ) ;
1166+ self . in_task ( |this| this. candidate_from_obligation_no_cache ( stack, recursion_depth ) ) ;
11321167
11331168 debug ! (
11341169 "CACHE MISS: SELECT({:?})={:?}" ,
@@ -1172,6 +1207,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11721207 fn candidate_from_obligation_no_cache < ' o > (
11731208 & mut self ,
11741209 stack : & TraitObligationStack < ' o , ' tcx > ,
1210+ recursion_depth : usize
11751211 ) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
11761212 if stack. obligation . predicate . references_error ( ) {
11771213 // If we encounter a `Error`, we generally prefer the
@@ -1189,13 +1225,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11891225 if self . intercrate_ambiguity_causes . is_some ( ) {
11901226 debug ! ( "evaluate_stack: intercrate_ambiguity_causes is some" ) ;
11911227 // Heuristics: show the diagnostics when there are no candidates in crate.
1192- if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
1228+ if let Ok ( candidate_set) = self . assemble_candidates ( stack, recursion_depth ) {
11931229 let mut no_candidates_apply = true ;
11941230 {
11951231 let evaluated_candidates = candidate_set
11961232 . vec
11971233 . iter ( )
1198- . map ( |c| self . evaluate_candidate ( stack, & c) ) ;
1234+ . map ( |c| self . evaluate_candidate ( stack, & c, recursion_depth ) ) ;
11991235
12001236 for ec in evaluated_candidates {
12011237 match ec {
@@ -1241,7 +1277,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12411277 return Ok ( None ) ;
12421278 }
12431279
1244- let candidate_set = self . assemble_candidates ( stack) ?;
1280+ let candidate_set = self . assemble_candidates ( stack, recursion_depth ) ?;
12451281
12461282 if candidate_set. ambiguous {
12471283 debug ! ( "candidate set contains ambig" ) ;
@@ -1288,7 +1324,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12881324 // is needed for specialization. Propagate overflow if it occurs.
12891325 let mut candidates = candidates
12901326 . into_iter ( )
1291- . map ( |c| match self . evaluate_candidate ( stack, & c) {
1327+ . map ( |c| match self . evaluate_candidate ( stack, & c, recursion_depth ) {
12921328 Ok ( eval) if eval. may_apply ( ) => Ok ( Some ( EvaluatedCandidate {
12931329 candidate : c,
12941330 evaluation : eval,
@@ -1526,6 +1562,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
15261562 fn assemble_candidates < ' o > (
15271563 & mut self ,
15281564 stack : & TraitObligationStack < ' o , ' tcx > ,
1565+ recursion_depth : usize
15291566 ) -> Result < SelectionCandidateSet < ' tcx > , SelectionError < ' tcx > > {
15301567 let TraitObligationStack { obligation, .. } = * stack;
15311568 let ref obligation = Obligation {
@@ -1601,7 +1638,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16011638 }
16021639
16031640 self . assemble_candidates_from_projected_tys ( obligation, & mut candidates) ;
1604- self . assemble_candidates_from_caller_bounds ( stack, & mut candidates) ?;
1641+ self . assemble_candidates_from_caller_bounds ( stack, & mut candidates, recursion_depth ) ?;
16051642 // Auto implementations have lower priority, so we only
16061643 // consider triggering a default if there is no other impl that can apply.
16071644 if candidates. vec . is_empty ( ) {
@@ -1734,6 +1771,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17341771 & mut self ,
17351772 stack : & TraitObligationStack < ' o , ' tcx > ,
17361773 candidates : & mut SelectionCandidateSet < ' tcx > ,
1774+ recursion_depth : usize
17371775 ) -> Result < ( ) , SelectionError < ' tcx > > {
17381776 debug ! (
17391777 "assemble_candidates_from_caller_bounds({:?})" ,
@@ -1755,7 +1793,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17551793 // keep only those bounds which may apply, and propagate overflow if it occurs
17561794 let mut param_candidates = vec ! [ ] ;
17571795 for bound in matching_bounds {
1758- let wc = self . evaluate_where_clause ( stack, bound. clone ( ) ) ?;
1796+ let wc = self . evaluate_where_clause ( stack, bound. clone ( ) , recursion_depth ) ?;
17591797 if wc. may_apply ( ) {
17601798 param_candidates. push ( ParamCandidate ( bound) ) ;
17611799 }
@@ -1770,11 +1808,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17701808 & mut self ,
17711809 stack : & TraitObligationStack < ' o , ' tcx > ,
17721810 where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > ,
1811+ recursion_depth : usize
17731812 ) -> Result < EvaluationResult , OverflowError > {
17741813 self . evaluation_probe ( |this| {
17751814 match this. match_where_clause_trait_ref ( stack. obligation , where_clause_trait_ref) {
17761815 Ok ( obligations) => {
1777- this. evaluate_predicates_recursively ( stack. list ( ) , obligations. iter ( ) )
1816+ this. evaluate_predicates_recursively ( stack. list ( ) , obligations. iter ( ) , recursion_depth )
17781817 }
17791818 Err ( ( ) ) => Ok ( EvaluatedToErr ) ,
17801819 }
0 commit comments