diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 0ff94097c8e..bd9eb12ee03 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -58,7 +58,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, -> Vec> { let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; - wf.compute_trait_ref(trait_ref); + wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -74,7 +74,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, // (*) ok to skip binders, because wf code is prepared for it match *predicate { ty::Predicate::Trait(ref t) => { - wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*) + wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*) } ty::Predicate::Equate(ref t) => { wf.compute(t.skip_binder().0); @@ -114,6 +114,12 @@ struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { out: Vec>, } +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +enum Elaborate { + All, + None, +} + impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) @@ -135,21 +141,24 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// Pushes the obligations required for `trait_ref` to be WF into /// `self.out`. - fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { + fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; - let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); - let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); - let implied_obligations = implied_obligations.map(|pred| { - traits::Obligation::new(cause.clone(), param_env, pred) - }); + if let Elaborate::All = elaborate { + let predicates = obligations.iter() + .map(|obligation| obligation.predicate.clone()) + .collect(); + let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + let implied_obligations = implied_obligations.map(|pred| { + traits::Obligation::new(cause.clone(), param_env, pred) + }); + self.out.extend(implied_obligations); + } - self.out.extend(implied_obligations.chain(obligations)); + self.out.extend(obligations); self.out.extend( trait_ref.substs.types() @@ -166,7 +175,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // WF and (b) the trait-ref holds. (It may also be // normalizable and be WF that way.) let trait_ref = data.trait_ref(self.infcx.tcx); - self.compute_trait_ref(&trait_ref); + self.compute_trait_ref(&trait_ref, Elaborate::All); if !data.has_escaping_regions() { let predicate = trait_ref.to_predicate();