Skip to content

Commit 4bbe532

Browse files
committed
Permit coinductive match only for purely OIBIT backtraces.
Better safe than sorry.
1 parent 3db82d1 commit 4bbe532

File tree

2 files changed

+39
-11
lines changed
  • src
    • librustc/middle/traits
    • librustc_data_structures/obligation_forest

2 files changed

+39
-11
lines changed

src/librustc/middle/traits/fulfill.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -359,17 +359,8 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
359359
let obligation = &pending_obligation.obligation;
360360
match obligation.predicate {
361361
ty::Predicate::Trait(ref data) => {
362-
// For defaulted traits, we use a co-inductive strategy to
363-
// solve, so that recursion is ok.
364-
if selcx.tcx().trait_has_default_impl(data.def_id()) {
365-
debug!("process_predicate: trait has default impl");
366-
for bt_obligation in backtrace {
367-
debug!("process_predicate: bt_obligation = {:?}", bt_obligation.obligation);
368-
if bt_obligation.obligation.predicate == obligation.predicate {
369-
debug!("process_predicate: found a match!");
370-
return Ok(Some(vec![]));
371-
}
372-
}
362+
if coinductive_match(selcx, obligation, data, &backtrace) {
363+
return Ok(Some(vec![]));
373364
}
374365

375366
let trait_obligation = obligation.with(data.clone());
@@ -483,6 +474,42 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
483474
}
484475
}
485476

477+
/// For defaulted traits, we use a co-inductive strategy to solve, so
478+
/// that recursion is ok. This routine returns true if the top of the
479+
/// stack (`top_obligation` and `top_data`):
480+
/// - is a defaulted trait, and
481+
/// - it also appears in the backtrace at some position `X`; and,
482+
/// - all the predicates at positions `X..` between `X` an the top are
483+
/// also defaulted traits.
484+
fn coinductive_match<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
485+
top_obligation: &PredicateObligation<'tcx>,
486+
top_data: &ty::PolyTraitPredicate<'tcx>,
487+
backtrace: &Backtrace<PendingPredicateObligation<'tcx>>)
488+
-> bool
489+
{
490+
if selcx.tcx().trait_has_default_impl(top_data.def_id()) {
491+
for bt_obligation in backtrace.clone() {
492+
// *Everything* in the backtrace must be a defaulted trait.
493+
match bt_obligation.obligation.predicate {
494+
ty::Predicate::Trait(ref data) => {
495+
if !selcx.tcx().trait_has_default_impl(data.def_id()) {
496+
break;
497+
}
498+
}
499+
_ => { break; }
500+
}
501+
502+
// And we must find a recursive match.
503+
if bt_obligation.obligation.predicate == top_obligation.predicate {
504+
debug!("process_predicate: found a match in the backtrace");
505+
return true;
506+
}
507+
}
508+
}
509+
510+
false
511+
}
512+
486513
fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
487514
r_b: ty::Region,
488515
cause: ObligationCause<'tcx>,

src/librustc_data_structures/obligation_forest/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ impl<O> Node<O> {
379379
}
380380
}
381381

382+
#[derive(Clone)]
382383
pub struct Backtrace<'b, O: 'b> {
383384
nodes: &'b [Node<O>],
384385
pointer: Option<NodeIndex>,

0 commit comments

Comments
 (0)