about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-01-01 13:15:14 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-01-01 18:48:26 -0500
commit7092af7ee317a42c8ad7d9f8d02bb9ff64891949 (patch)
tree030c23ecbf3d5d3f9bb0860266740ecbac5f3b70
parent39d74026663597a8d4ad0ab04e6d117bf9fd6ad4 (diff)
downloadrust-7092af7ee317a42c8ad7d9f8d02bb9ff64891949.tar.gz
rust-7092af7ee317a42c8ad7d9f8d02bb9ff64891949.zip
Normalize predicates found on the impl
-rw-r--r--src/librustc/middle/traits/project.rs38
-rw-r--r--src/librustc/middle/traits/select.rs20
2 files changed, 49 insertions, 9 deletions
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 28a826b859b..c84f31bf6c3 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -102,7 +102,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
 
 /// Compute result of projecting an associated type and unify it with
 /// `obligation.predicate.ty` (if we can).
-pub fn project_and_unify_type<'cx,'tcx>(
+fn project_and_unify_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &ProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
@@ -135,9 +135,19 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
                                cause: ObligationCause<'tcx>,
                                value: &T)
                                -> Normalized<'tcx, T>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone
+    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
 {
-    let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, 0);
+    normalize_with_depth(selcx, cause, 0, value)
+}
+
+pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
+                                          cause: ObligationCause<'tcx>,
+                                          depth: uint,
+                                          value: &T)
+                                          -> Normalized<'tcx, T>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+{
+    let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
     let result = normalizer.fold(value);
     Normalized {
         value: result,
@@ -278,9 +288,10 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
             // an impl, where-clause etc) and hence we must
             // re-normalize it
 
-            debug!("normalize_projection_type: projected_ty={} depth={}",
+            debug!("normalize_projection_type: projected_ty={} depth={} obligations={}",
                    projected_ty.repr(selcx.tcx()),
-                   depth);
+                   depth,
+                   obligations.repr(selcx.tcx()));
 
             if ty::type_has_projection(projected_ty) {
                 let tcx = selcx.tcx();
@@ -644,3 +655,20 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
         }
     }
 }
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Normalized<'tcx, T> {
+        Normalized {
+            value: self.value.fold_with(folder),
+            obligations: self.obligations.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Normalized<'tcx, T> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("Normalized({},{})",
+                self.value.repr(tcx),
+                self.obligations.repr(tcx))
+    }
+}
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index ce5337a58e1..3837cb97228 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -18,6 +18,7 @@ use self::BuiltinBoundConditions::*;
 use self::EvaluationResult::*;
 
 use super::{DerivedObligationCause};
+use super::{project};
 use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
 use super::{ObligationCauseCode, BuiltinDerivedObligation};
 use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
@@ -29,7 +30,7 @@ use super::{util};
 
 use middle::fast_reject;
 use middle::mem_categorization::Typer;
-use middle::subst::{Subst, Substs, VecPerParamSpace};
+use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
 use middle::ty::{mod, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
@@ -2100,7 +2101,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    fn impl_predicates(&self,
+    fn impl_predicates(&mut self,
                        cause: ObligationCause<'tcx>,
                        recursion_depth: uint,
                        impl_def_id: ast::DefId,
@@ -2111,8 +2112,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
         let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
-        let bounds = self.infcx().plug_leaks(skol_map, snapshot, &bounds);
-        util::predicates_for_generics(self.tcx(), cause, recursion_depth, &bounds)
+        let normalized_bounds =
+            project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds);
+        let normalized_bounds =
+            self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds);
+        let mut impl_obligations =
+            util::predicates_for_generics(self.tcx(),
+                                          cause,
+                                          recursion_depth,
+                                          &normalized_bounds.value);
+        for obligation in normalized_bounds.obligations.into_iter() {
+            impl_obligations.push(TypeSpace, obligation);
+        }
+        impl_obligations
     }
 
     fn fn_family_trait_kind(&self,