]> git.lizzy.rs Git - rust.git/commitdiff
Do not elaborate trait obligations in where clauses
authorscalexm <martin.alex32@hotmail.fr>
Thu, 10 Aug 2017 13:52:08 +0000 (15:52 +0200)
committerscalexm <martin.alex32@hotmail.fr>
Thu, 10 Aug 2017 13:52:08 +0000 (15:52 +0200)
src/librustc/ty/wf.rs

index 0ff94097c8ede5141ed863011fdfee1684c2ee39..bd9eb12ee03a22627e56b3a9eb8c944c83afa981 100644 (file)
@@ -58,7 +58,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                          -> Vec<traits::PredicateObligation<'tcx>>
 {
     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<traits::PredicateObligation<'tcx>>,
 }
 
+#[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 @@ fn normalize(&mut self) -> Vec<traits::PredicateObligation<'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 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'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();