use middle::lang_items;
use rustc_data_structures::bitvec::BitVector;
-use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
use std::iter;
use std::cell::RefCell;
use std::cmp;
use std::fmt;
-use std::marker::PhantomData;
use std::mem;
use std::rc::Rc;
use syntax::abi::Abi;
use lint;
use util::nodemap::{FxHashMap, FxHashSet};
-struct InferredObligationsSnapshotVecDelegate<'tcx> {
- phantom: PhantomData<&'tcx i32>,
-}
-impl<'tcx> SnapshotVecDelegate for InferredObligationsSnapshotVecDelegate<'tcx> {
- type Value = PredicateObligation<'tcx>;
- type Undo = ();
- fn reverse(_: &mut Vec<Self::Value>, _: Self::Undo) {}
-}
pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
/// would satisfy it. This avoids crippling inference, basically.
intercrate: Option<IntercrateMode>,
- inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
-
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
/// Controls whether or not to filter out negative impls when selecting.
infcx,
freshener: infcx.freshener(),
intercrate: None,
- inferred_obligations: SnapshotVec::new(),
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
}
infcx,
freshener: infcx.freshener(),
intercrate: Some(mode),
- inferred_obligations: SnapshotVec::new(),
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
}
infcx,
freshener: infcx.freshener(),
intercrate: None,
- inferred_obligations: SnapshotVec::new(),
intercrate_ambiguity_causes: None,
allow_negative_impls,
}
fn in_snapshot<R, F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
{
- // The irrefutable nature of the operation means we don't need to snapshot the
- // inferred_obligations vector.
self.infcx.in_snapshot(|snapshot| f(self, snapshot))
}
fn probe<R, F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
{
- let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
- let result = self.infcx.probe(|snapshot| f(self, snapshot));
- self.inferred_obligations.rollback_to(inferred_obligations_snapshot);
- result
+ self.infcx.probe(|snapshot| f(self, snapshot))
}
/// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if
fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E> where
F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> Result<T, E>
{
- let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
- match self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) {
- Ok(ok) => {
- self.inferred_obligations.commit(inferred_obligations_snapshot);
- Ok(ok)
- },
- Err(err) => {
- self.inferred_obligations.rollback_to(inferred_obligations_snapshot);
- Err(err)
- }
- }
+ self.infcx.commit_if_ok(|snapshot| f(self, snapshot))
}
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
let ret = match self.candidate_from_obligation(&stack)? {
None => None,
- Some(candidate) => {
- let mut candidate = self.confirm_candidate(obligation, candidate)?;
- let inferred_obligations = (*self.inferred_obligations).into_iter().cloned();
- candidate.nested_obligations_mut().extend(inferred_obligations);
- Some(candidate)
- },
+ Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
};
// Test whether this is a `()` which was produced by defaulting a
stack: TraitObligationStackList<'o, 'tcx>,
predicates: I)
-> EvaluationResult
- where I : Iterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
+ where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
{
let mut result = EvaluatedToOk;
for obligation in predicates {
// does this code ever run?
match self.infcx.equality_predicate(&obligation.cause, obligation.param_env, p) {
Ok(InferOk { obligations, .. }) => {
- self.inferred_obligations.extend(obligations);
+ self.evaluate_predicates_recursively(previous_stack, &obligations);
EvaluatedToOk
},
Err(_) => EvaluatedToErr
// does this code ever run?
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
Some(Ok(InferOk { obligations, .. })) => {
- self.inferred_obligations.extend(obligations);
+ self.evaluate_predicates_recursively(previous_stack, &obligations);
EvaluatedToOk
},
Some(Err(_)) => EvaluatedToErr,
-> bool
{
assert!(!skol_trait_ref.has_escaping_regions());
- match self.infcx.at(&obligation.cause, obligation.param_env)
- .sup(ty::Binder(skol_trait_ref), trait_bound) {
- Ok(InferOk { obligations, .. }) => {
- self.inferred_obligations.extend(obligations);
- }
- Err(_) => { return false; }
+ if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env)
+ .sup(ty::Binder(skol_trait_ref), trait_bound) {
+ return false;
}
self.infcx.leak_check(false, obligation.cause.span, skol_map, snapshot).is_ok()
};
let mut upcast_trait_ref = None;
+ let mut nested = vec![];
let vtable_base;
{
self.commit_if_ok(
|this, _| this.match_poly_trait_ref(obligation, t))
{
- Ok(_) => { upcast_trait_ref = Some(t); false }
+ Ok(obligations) => {
+ upcast_trait_ref = Some(t);
+ nested.extend(obligations);
+ false
+ }
Err(_) => { true }
}
});
VtableObjectData {
upcast_trait_ref: upcast_trait_ref.unwrap(),
vtable_base,
- nested: vec![]
+ nested,
}
}
self.generator_trait_ref_unnormalized(obligation, closure_def_id, substs);
let Normalized {
value: trait_ref,
- obligations
+ mut obligations
} = normalize_with_depth(self,
obligation.param_env,
obligation.cause.clone(),
trait_ref,
obligations);
- self.confirm_poly_trait_refs(obligation.cause.clone(),
- obligation.param_env,
- obligation.predicate.to_poly_trait_ref(),
- trait_ref)?;
+ obligations.extend(
+ self.confirm_poly_trait_refs(obligation.cause.clone(),
+ obligation.param_env,
+ obligation.predicate.to_poly_trait_ref(),
+ trait_ref)?);
Ok(VtableGeneratorData {
closure_def_id: closure_def_id,
trait_ref,
obligations);
- self.confirm_poly_trait_refs(obligation.cause.clone(),
- obligation.param_env,
- obligation.predicate.to_poly_trait_ref(),
- trait_ref)?;
+ obligations.extend(
+ self.confirm_poly_trait_refs(obligation.cause.clone(),
+ obligation.param_env,
+ obligation.predicate.to_poly_trait_ref(),
+ trait_ref)?);
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation_param_env: ty::ParamEnv<'tcx>,
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
expected_trait_ref: ty::PolyTraitRef<'tcx>)
- -> Result<(), SelectionError<'tcx>>
+ -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>>
{
let obligation_trait_ref = obligation_trait_ref.clone();
self.infcx
.at(&obligation_cause, obligation_param_env)
.sup(obligation_trait_ref, expected_trait_ref)
- .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
+ .map(|InferOk { obligations, .. }| obligations)
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
}
self.infcx.at(&obligation.cause, obligation.param_env)
.eq(target, new_trait)
.map_err(|_| Unimplemented)?;
- self.inferred_obligations.extend(obligations);
+ nested.extend(obligations);
// Register one obligation for 'a: 'b.
let cause = ObligationCause::new(obligation.cause.span,
self.infcx.at(&obligation.cause, obligation.param_env)
.eq(b, a)
.map_err(|_| Unimplemented)?;
- self.inferred_obligations.extend(obligations);
+ nested.extend(obligations);
}
// Struct<T> -> Struct<U>.
self.infcx.at(&obligation.cause, obligation.param_env)
.eq(target, new_struct)
.map_err(|_| Unimplemented)?;
- self.inferred_obligations.extend(obligations);
+ nested.extend(obligations);
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
nested.push(tcx.predicate_for_trait_def(
self.infcx.at(&obligation.cause, obligation.param_env)
.eq(target, new_tuple)
.map_err(|_| Unimplemented)?;
- self.inferred_obligations.extend(obligations);
+ nested.extend(obligations);
// Construct the nested T: Unsize<U> predicate.
nested.push(tcx.predicate_for_trait_def(
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
impl_substs);
- let impl_trait_ref =
+ let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
project::normalize_with_depth(self,
obligation.param_env,
obligation.cause.clone(),
let InferOk { obligations, .. } =
self.infcx.at(&obligation.cause, obligation.param_env)
- .eq(skol_obligation_trait_ref, impl_trait_ref.value)
+ .eq(skol_obligation_trait_ref, impl_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e);
()
})?;
- self.inferred_obligations.extend(obligations);
+ nested_obligations.extend(obligations);
if let Err(e) = self.infcx.leak_check(false,
obligation.cause.span,
debug!("match_impl: success impl_substs={:?}", impl_substs);
Ok((Normalized {
value: impl_substs,
- obligations: impl_trait_ref.obligations
+ obligations: nested_obligations
}, skol_map))
}
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-> Result<Vec<PredicateObligation<'tcx>>,()>
{
- self.match_poly_trait_ref(obligation, where_clause_trait_ref)?;
- Ok(Vec::new())
+ self.match_poly_trait_ref(obligation, where_clause_trait_ref)
}
/// Returns `Ok` if `poly_trait_ref` being true implies that the
fn match_poly_trait_ref(&mut self,
obligation: &TraitObligation<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>)
- -> Result<(),()>
+ -> Result<Vec<PredicateObligation<'tcx>>,()>
{
debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
obligation,
self.infcx.at(&obligation.cause, obligation.param_env)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
- .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
+ .map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())
}