mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 16:45:37 +00:00
Permit coinductive match only for purely OIBIT backtraces.
Better safe than sorry.
This commit is contained in:
parent
3db82d1a4e
commit
4bbe532737
@ -359,18 +359,9 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
|||||||
let obligation = &pending_obligation.obligation;
|
let obligation = &pending_obligation.obligation;
|
||||||
match obligation.predicate {
|
match obligation.predicate {
|
||||||
ty::Predicate::Trait(ref data) => {
|
ty::Predicate::Trait(ref data) => {
|
||||||
// For defaulted traits, we use a co-inductive strategy to
|
if coinductive_match(selcx, obligation, data, &backtrace) {
|
||||||
// solve, so that recursion is ok.
|
|
||||||
if selcx.tcx().trait_has_default_impl(data.def_id()) {
|
|
||||||
debug!("process_predicate: trait has default impl");
|
|
||||||
for bt_obligation in backtrace {
|
|
||||||
debug!("process_predicate: bt_obligation = {:?}", bt_obligation.obligation);
|
|
||||||
if bt_obligation.obligation.predicate == obligation.predicate {
|
|
||||||
debug!("process_predicate: found a match!");
|
|
||||||
return Ok(Some(vec![]));
|
return Ok(Some(vec![]));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let trait_obligation = obligation.with(data.clone());
|
let trait_obligation = obligation.with(data.clone());
|
||||||
match selcx.select(&trait_obligation) {
|
match selcx.select(&trait_obligation) {
|
||||||
@ -483,6 +474,42 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For defaulted traits, we use a co-inductive strategy to solve, so
|
||||||
|
/// that recursion is ok. This routine returns true if the top of the
|
||||||
|
/// stack (`top_obligation` and `top_data`):
|
||||||
|
/// - is a defaulted trait, and
|
||||||
|
/// - it also appears in the backtrace at some position `X`; and,
|
||||||
|
/// - all the predicates at positions `X..` between `X` an the top are
|
||||||
|
/// also defaulted traits.
|
||||||
|
fn coinductive_match<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
||||||
|
top_obligation: &PredicateObligation<'tcx>,
|
||||||
|
top_data: &ty::PolyTraitPredicate<'tcx>,
|
||||||
|
backtrace: &Backtrace<PendingPredicateObligation<'tcx>>)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
if selcx.tcx().trait_has_default_impl(top_data.def_id()) {
|
||||||
|
for bt_obligation in backtrace.clone() {
|
||||||
|
// *Everything* in the backtrace must be a defaulted trait.
|
||||||
|
match bt_obligation.obligation.predicate {
|
||||||
|
ty::Predicate::Trait(ref data) => {
|
||||||
|
if !selcx.tcx().trait_has_default_impl(data.def_id()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// And we must find a recursive match.
|
||||||
|
if bt_obligation.obligation.predicate == top_obligation.predicate {
|
||||||
|
debug!("process_predicate: found a match in the backtrace");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
|
fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
|
||||||
r_b: ty::Region,
|
r_b: ty::Region,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
@ -379,6 +379,7 @@ impl<O> Node<O> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Backtrace<'b, O: 'b> {
|
pub struct Backtrace<'b, O: 'b> {
|
||||||
nodes: &'b [Node<O>],
|
nodes: &'b [Node<O>],
|
||||||
pointer: Option<NodeIndex>,
|
pointer: Option<NodeIndex>,
|
||||||
|
Loading…
Reference in New Issue
Block a user