Skip to content

Commit 54fd8ca

Browse files
committed
Remove extra recursion_depth tracking
1 parent c55c312 commit 54fd8ca

File tree

1 file changed

+41
-63
lines changed

1 file changed

+41
-63
lines changed

src/librustc/traits/select.rs

Lines changed: 41 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc_data_structures::bit_set::GrowableBitSet;
4242
use rustc_data_structures::sync::Lock;
4343
use rustc_target::spec::abi::Abi;
4444
use std::cmp;
45-
use std::fmt::{self, Display};
45+
use std::fmt;
4646
use std::iter;
4747
use std::rc::Rc;
4848
use util::nodemap::{FxHashMap, FxHashSet};
@@ -573,9 +573,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
573573

574574
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
575575

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) {
576+
let candidate = match self.candidate_from_obligation(&stack) {
579577
Err(SelectionError::Overflow) => {
580578
// In standard mode, overflow must have been caught and reported
581579
// earlier.
@@ -631,9 +629,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
631629
obligation: &PredicateObligation<'tcx>,
632630
) -> Result<EvaluationResult, OverflowError> {
633631
self.evaluation_probe(|this| {
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)
632+
this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation.clone())
637633
})
638634
}
639635

@@ -657,15 +653,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
657653
&mut self,
658654
stack: TraitObligationStackList<'o, 'tcx>,
659655
predicates: I,
660-
recursion_depth: usize
661656
) -> Result<EvaluationResult, OverflowError>
662657
where
663-
I: IntoIterator<Item = &'a PredicateObligation<'tcx>>,
658+
I: IntoIterator<Item = PredicateObligation<'tcx>>,
664659
'tcx: 'a,
665660
{
666661
let mut result = EvaluatedToOk;
667662
for obligation in predicates {
668-
let eval = self.evaluate_predicate_recursively(stack, obligation, recursion_depth)?;
663+
let eval = self.evaluate_predicate_recursively(stack, obligation)?;
669664
debug!(
670665
"evaluate_predicate_recursively({:?}) = {:?}",
671666
obligation, eval
@@ -684,32 +679,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
684679
fn evaluate_predicate_recursively<'o>(
685680
&mut self,
686681
previous_stack: TraitObligationStackList<'o, 'tcx>,
687-
obligation: &PredicateObligation<'tcx>,
688-
mut recursion_depth: usize
682+
obligation: PredicateObligation<'tcx>,
689683
) -> Result<EvaluationResult, OverflowError> {
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;
684+
debug!("evaluate_predicate_recursively({:?})", obligation);
685+
self.check_recursion_limit(obligation)?;
706686

707687
match obligation.predicate {
708688
ty::Predicate::Trait(ref t) => {
709689
debug_assert!(!t.has_escaping_bound_vars());
710-
let obligation = obligation.with(t.clone());
711-
self.evaluate_trait_predicate_recursively(previous_stack, obligation,
712-
recursion_depth)
690+
let mut obligation = obligation.with(t.clone());
691+
obligation.recursion_depth += 1
692+
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
713693
}
714694

715695
ty::Predicate::Subtype(ref p) => {
@@ -718,8 +698,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
718698
.subtype_predicate(&obligation.cause, obligation.param_env, p)
719699
{
720700
Some(Ok(InferOk { obligations, .. })) => {
721-
self.evaluate_predicates_recursively(previous_stack, &obligations,
722-
recursion_depth)
701+
for o in obligations.iter_mut() {
702+
o.recursion_depth += 1
703+
}
704+
self.evaluate_predicates_recursively(previous_stack, obligation.into_iter())
723705
}
724706
Some(Err(_)) => Ok(EvaluatedToErr),
725707
None => Ok(EvaluatedToAmbig),
@@ -734,8 +716,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
734716
obligation.cause.span,
735717
) {
736718
Some(obligations) => {
737-
self.evaluate_predicates_recursively(previous_stack, obligations.iter(),
738-
recursion_depth)
719+
for o in obligations.iter_mut() {
720+
o.recursion_depth += 1
721+
}
722+
self.evaluate_predicates_recursively(previous_stack, obligations.iter())
739723
}
740724
None => Ok(EvaluatedToAmbig),
741725
},
@@ -758,10 +742,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
758742
let project_obligation = obligation.with(data.clone());
759743
match project::poly_project_and_unify_type(self, &project_obligation) {
760744
Ok(Some(subobligations)) => {
745+
for o in subobligations.iter_mut() {
746+
o.recursion_depth += 1
747+
}
761748
let result = self.evaluate_predicates_recursively(
762749
previous_stack,
763-
subobligations.iter(),
764-
recursion_depth
750+
subobligations.into_iter(),
765751
);
766752
if let Some(key) =
767753
ProjectionCacheKey::from_poly_projection_predicate(self, data)
@@ -820,7 +806,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
820806
&mut self,
821807
previous_stack: TraitObligationStackList<'o, 'tcx>,
822808
mut obligation: TraitObligation<'tcx>,
823-
recursion_depth: usize
824809
) -> Result<EvaluationResult, OverflowError> {
825810
debug!("evaluate_trait_predicate_recursively({:?})", obligation);
826811

@@ -848,7 +833,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
848833
return Ok(result);
849834
}
850835

851-
let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack, recursion_depth));
836+
let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
852837
let result = result?;
853838

854839
debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result);
@@ -860,7 +845,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
860845
fn evaluate_stack<'o>(
861846
&mut self,
862847
stack: &TraitObligationStack<'o, 'tcx>,
863-
recursion_depth: usize
864848
) -> Result<EvaluationResult, OverflowError> {
865849
// In intercrate mode, whenever any of the types are unbound,
866850
// there can always be an impl. Even if there are no impls in
@@ -901,7 +885,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
901885
// Heuristics: show the diagnostics when there are no candidates in crate.
902886
if self.intercrate_ambiguity_causes.is_some() {
903887
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
904-
if let Ok(candidate_set) = self.assemble_candidates(stack, recursion_depth) {
888+
if let Ok(candidate_set) = self.assemble_candidates(stack) {
905889
if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
906890
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
907891
let self_ty = trait_ref.self_ty();
@@ -982,8 +966,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
982966
}
983967
}
984968

985-
match self.candidate_from_obligation(stack, recursion_depth) {
986-
Ok(Some(c)) => self.evaluate_candidate(stack, &c, recursion_depth),
969+
match self.candidate_from_obligation(stack) {
970+
Ok(Some(c)) => self.evaluate_candidate(stack, &c),
987971
Ok(None) => Ok(EvaluatedToAmbig),
988972
Err(Overflow) => Err(OverflowError),
989973
Err(..) => Ok(EvaluatedToErr),
@@ -1022,7 +1006,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10221006
&mut self,
10231007
stack: &TraitObligationStack<'o, 'tcx>,
10241008
candidate: &SelectionCandidate<'tcx>,
1025-
recursion_depth: usize
10261009
) -> Result<EvaluationResult, OverflowError> {
10271010
debug!(
10281011
"evaluate_candidate: depth={} candidate={:?}",
@@ -1034,7 +1017,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
10341017
Ok(selection) => this.evaluate_predicates_recursively(
10351018
stack.list(),
10361019
selection.nested_obligations().iter(),
1037-
recursion_depth
10381020
),
10391021
Err(..) => Ok(EvaluatedToErr),
10401022
}
@@ -1109,13 +1091,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11091091
.insert(trait_ref, WithDepNode::new(dep_node, result));
11101092
}
11111093

1094+
// Check that the recursion limit has not been exceeded.
1095+
//
11121096
// The weird return type of this function allows it to be used with the 'try' (?)
11131097
// operator within certain functions
1114-
fn check_recursion_limit<T: Display + TypeFoldable<'tcx>>(&self, recursion_depth: usize,
1115-
obligation: &Obligation<'tcx, T>,
1098+
fn check_recursion_limit<T: Display + TypeFoldable<'tcx>>(&self, obligation: &Obligation<'tcx, T>,
11161099
) -> Result<(), OverflowError> {
11171100
let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
1118-
if recursion_depth >= recursion_limit {
1101+
if obligaton.recursion_depth >= recursion_limit {
11191102
match self.query_mode {
11201103
TraitQueryMode::Standard => {
11211104
self.infcx().report_overflow_error(obligation, true);
@@ -1141,11 +1124,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11411124
fn candidate_from_obligation<'o>(
11421125
&mut self,
11431126
stack: &TraitObligationStack<'o, 'tcx>,
1144-
recursion_depth: usize
11451127
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
11461128
// Watch out for overflow. This intentionally bypasses (and does
11471129
// not update) the cache.
1148-
self.check_recursion_limit(stack.obligation.recursion_depth, &stack.obligation)?;
1130+
self.check_recursion_limit(&stack.obligation)?;
1131+
11491132

11501133
// Check the cache. Note that we freshen the trait-ref
11511134
// separately rather than using `stack.fresh_trait_ref` --
@@ -1167,7 +1150,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
11671150

11681151
// If no match, compute result and insert into cache.
11691152
let (candidate, dep_node) =
1170-
self.in_task(|this| this.candidate_from_obligation_no_cache(stack, recursion_depth));
1153+
self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
11711154

11721155
debug!(
11731156
"CACHE MISS: SELECT({:?})={:?}",
@@ -1211,7 +1194,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12111194
fn candidate_from_obligation_no_cache<'o>(
12121195
&mut self,
12131196
stack: &TraitObligationStack<'o, 'tcx>,
1214-
recursion_depth: usize
12151197
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
12161198
if stack.obligation.predicate.references_error() {
12171199
// If we encounter a `Error`, we generally prefer the
@@ -1229,13 +1211,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12291211
if self.intercrate_ambiguity_causes.is_some() {
12301212
debug!("evaluate_stack: intercrate_ambiguity_causes is some");
12311213
// Heuristics: show the diagnostics when there are no candidates in crate.
1232-
if let Ok(candidate_set) = self.assemble_candidates(stack, recursion_depth) {
1214+
if let Ok(candidate_set) = self.assemble_candidates(stack) {
12331215
let mut no_candidates_apply = true;
12341216
{
12351217
let evaluated_candidates = candidate_set
12361218
.vec
12371219
.iter()
1238-
.map(|c| self.evaluate_candidate(stack, &c, recursion_depth));
1220+
.map(|c| self.evaluate_candidate(stack, &c));
12391221

12401222
for ec in evaluated_candidates {
12411223
match ec {
@@ -1281,7 +1263,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12811263
return Ok(None);
12821264
}
12831265

1284-
let candidate_set = self.assemble_candidates(stack, recursion_depth)?;
1266+
let candidate_set = self.assemble_candidates(stack)?;
12851267

12861268
if candidate_set.ambiguous {
12871269
debug!("candidate set contains ambig");
@@ -1328,7 +1310,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
13281310
// is needed for specialization. Propagate overflow if it occurs.
13291311
let mut candidates = candidates
13301312
.into_iter()
1331-
.map(|c| match self.evaluate_candidate(stack, &c, recursion_depth) {
1313+
.map(|c| match self.evaluate_candidate(stack, &c) {
13321314
Ok(eval) if eval.may_apply() => Ok(Some(EvaluatedCandidate {
13331315
candidate: c,
13341316
evaluation: eval,
@@ -1566,7 +1548,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
15661548
fn assemble_candidates<'o>(
15671549
&mut self,
15681550
stack: &TraitObligationStack<'o, 'tcx>,
1569-
recursion_depth: usize
15701551
) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
15711552
let TraitObligationStack { obligation, .. } = *stack;
15721553
let ref obligation = Obligation {
@@ -1642,7 +1623,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16421623
}
16431624

16441625
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
1645-
self.assemble_candidates_from_caller_bounds(stack, &mut candidates, recursion_depth)?;
1626+
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
16461627
// Auto implementations have lower priority, so we only
16471628
// consider triggering a default if there is no other impl that can apply.
16481629
if candidates.vec.is_empty() {
@@ -1775,7 +1756,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17751756
&mut self,
17761757
stack: &TraitObligationStack<'o, 'tcx>,
17771758
candidates: &mut SelectionCandidateSet<'tcx>,
1778-
recursion_depth: usize
17791759
) -> Result<(), SelectionError<'tcx>> {
17801760
debug!(
17811761
"assemble_candidates_from_caller_bounds({:?})",
@@ -1797,7 +1777,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17971777
// keep only those bounds which may apply, and propagate overflow if it occurs
17981778
let mut param_candidates = vec![];
17991779
for bound in matching_bounds {
1800-
let wc = self.evaluate_where_clause(stack, bound.clone(), recursion_depth)?;
1780+
let wc = self.evaluate_where_clause(stack, bound.clone())?;
18011781
if wc.may_apply() {
18021782
param_candidates.push(ParamCandidate(bound));
18031783
}
@@ -1812,13 +1792,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
18121792
&mut self,
18131793
stack: &TraitObligationStack<'o, 'tcx>,
18141794
where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
1815-
recursion_depth: usize
18161795
) -> Result<EvaluationResult, OverflowError> {
18171796
self.evaluation_probe(|this| {
18181797
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
18191798
Ok(obligations) => {
1820-
this.evaluate_predicates_recursively(stack.list(), obligations.iter(),
1821-
recursion_depth)
1799+
this.evaluate_predicates_recursively(stack.list(), obligations.iter())
18221800
}
18231801
Err(()) => Ok(EvaluatedToErr),
18241802
}

0 commit comments

Comments
 (0)