1
Fork 0

Do not elaborate trait obligations in where clauses

This commit is contained in:
scalexm 2017-08-10 15:52:08 +02:00
parent e3b28b4ae8
commit 94703ce3f7

View file

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