]> git.lizzy.rs Git - rust.git/commitdiff
Integrate projection bounds to `ExistentialBounds` but do not use them for anything.
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 26 Dec 2014 09:36:04 +0000 (04:36 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 30 Dec 2014 14:36:21 +0000 (09:36 -0500)
14 files changed:
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/infer/coercion.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/util/ppaux.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/assoc.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/vtable.rs
src/librustdoc/clean/mod.rs

index 2a4d5f36a17c9532c06d715876a1780b944c3536..7dccc49dcbbdac2776f7a21da0a8c50db01259ca 100644 (file)
@@ -200,9 +200,9 @@ pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
     parse_bounds(&mut st, conv)
 }
 
-pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum,
-                                     pos: uint, tcx: &ty::ctxt, conv: conv_did)
-                                     -> ty::ExistentialBounds {
+pub fn parse_existential_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
+                                           pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
+                                           -> ty::ExistentialBounds<'tcx> {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_existential_bounds(&mut st, conv)
 }
@@ -744,10 +744,18 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
     }
 }
 
-fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds {
-    let r = parse_region(st, |x,y| conv(x,y));
-    let bb = parse_builtin_bounds(st, conv);
-    return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb };
+fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
+                                     conv: conv_did)
+                                     -> ty::ExistentialBounds<'tcx>
+{
+    let ty::ParamBounds { trait_bounds, mut region_bounds, builtin_bounds, projection_bounds } =
+         parse_bounds(st, conv);
+    assert_eq!(region_bounds.len(), 1);
+    assert_eq!(trait_bounds.len(), 0);
+    let region_bound = region_bounds.pop().unwrap();
+    return ty::ExistentialBounds { region_bound: region_bound,
+                                   builtin_bounds: builtin_bounds,
+                                   projection_bounds: projection_bounds };
 }
 
 fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {
index 015724d38eee6d6f670ce993106c896debd99fe8..b6d05882dce23bff5223a96d463b86f31b6704d0 100644 (file)
@@ -392,9 +392,14 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti
     mywrite!(w, ".");
 }
 
-pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ExistentialBounds) {
-    enc_region(w, cx, bs.region_bound);
-    enc_builtin_bounds(w, cx, &bs.builtin_bounds);
+pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
+                                       cx: &ctxt<'a,'tcx>,
+                                       bs: &ty::ExistentialBounds<'tcx>) {
+    let param_bounds = ty::ParamBounds { trait_bounds: vec!(),
+                                         region_bounds: vec!(bs.region_bound),
+                                         builtin_bounds: bs.builtin_bounds,
+                                         projection_bounds: bs.projection_bounds.clone() };
+    enc_bounds(w, cx, &param_bounds);
 }
 
 pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
index 4dee3ee471365bc8c40e1283ab8a4fa4b162ab85..0b78f2b1cfce9bdefb65f34101cf9d3fc70d9825 100644 (file)
@@ -842,7 +842,8 @@ fn emit_type_scheme<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                             type_scheme: ty::TypeScheme<'tcx>);
     fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                        substs: &subst::Substs<'tcx>);
-    fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds);
+    fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
+                                   bounds: &ty::ExistentialBounds<'tcx>);
     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
     fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                                 adj: &ty::AutoAdjustment<'tcx>);
@@ -982,7 +983,8 @@ fn emit_type_scheme<'b>(&mut self,
         });
     }
 
-    fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds) {
+    fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
+                                   bounds: &ty::ExistentialBounds<'tcx>) {
         self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
                                                                     &ecx.ty_str_ctxt(),
                                                                     bounds)));
@@ -1372,7 +1374,7 @@ fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
     fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                 -> ty::TypeScheme<'tcx>;
     fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                       -> ty::ExistentialBounds;
+                                       -> ty::ExistentialBounds<'tcx>;
     fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                            -> subst::Substs<'tcx>;
     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1626,7 +1628,7 @@ fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
     }
 
     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                       -> ty::ExistentialBounds
+                                       -> ty::ExistentialBounds<'tcx>
     {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_existential_bounds_data(doc.data,
index 13017da508d28eada44d42e871878c6540ddf07c..11ca202971e1d5b77f437585099f345df98049ac 100644 (file)
@@ -351,11 +351,11 @@ fn unsize_ty(&self,
                 (&ty::ty_trait(..), &ty::ty_trait(..)) => {
                     None
                 }
-                (_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => {
+                (_, &ty::ty_trait(box ty::TyTrait { ref principal, ref bounds })) => {
                     // FIXME what is the purpose of `ty`?
-                    let ty = ty::mk_trait(tcx, principal.clone(), bounds);
-                    Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(),
-                                                             bounds: bounds },
+                    let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone());
+                    Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(),
+                                                             bounds: bounds.clone() },
                                                ty_a)))
                 }
                 (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
@@ -458,10 +458,9 @@ fn coerce_object<F, G>(&self,
 
         match a.sty {
             ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
-                ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
+                ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
                     debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
-                    // FIXME what is purpose of this type `tr`?
-                    let tr = ty::mk_trait(tcx, principal.clone(), bounds);
+                    let tr = ty::mk_trait(tcx, principal.clone(), bounds.clone());
                     try!(self.subtype(mk_ty(tr), b));
                     Ok(Some(AdjustDerefRef(AutoDerefRef {
                         autoderefs: 1,
index 4114394041dc36c6aaabca4445ad1849aa9bcc78..e0bcdfc6d8d9375627b5702d13e4411349553548 100644 (file)
@@ -222,7 +222,7 @@ fn closure_tys(&self, a: &ty::ClosureTy<'tcx>,
         };
         let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
         let onceness = try!(self.oncenesses(a.onceness, b.onceness));
-        let bounds = try!(self.existential_bounds(a.bounds, b.bounds));
+        let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds));
         let sig = try!(self.binders(&a.sig, &b.sig));
         let abi = try!(self.abi(a.abi, b.abi));
         Ok(ty::ClosureTy {
@@ -289,15 +289,61 @@ fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> {
 
     fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<'tcx, Onceness>;
 
+    fn projection_tys(&self,
+                      a: &ty::ProjectionTy<'tcx>,
+                      b: &ty::ProjectionTy<'tcx>)
+                      -> cres<'tcx, ty::ProjectionTy<'tcx>>
+    {
+        if a.item_name != b.item_name {
+            Err(ty::terr_projection_name_mismatched(
+                expected_found(self, a.item_name, b.item_name)))
+        } else {
+            let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
+            Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
+        }
+    }
+
+    fn projection_predicates(&self,
+                             a: &ty::ProjectionPredicate<'tcx>,
+                             b: &ty::ProjectionPredicate<'tcx>)
+                             -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
+    {
+        let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty));
+        let ty = try!(self.tys(a.ty, b.ty));
+        Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
+    }
+
+    fn projection_bounds(&self,
+                         a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
+                         b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
+                         -> cres<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
+    {
+        // To be compatible, `a` and `b` must be for precisely the
+        // same set of traits and item names. We always require that
+        // projection bounds lists are sorted by trait-def-id and item-name,
+        // so we can just iterate through the lists pairwise, so long as they are the
+        // same length.
+        if a.len() != b.len() {
+            Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len())))
+        } else {
+            a.iter()
+                .zip(b.iter())
+                .map(|(a, b)| self.binders(a, b))
+                .collect()
+        }
+    }
+
     fn existential_bounds(&self,
-                          a: ty::ExistentialBounds,
-                          b: ty::ExistentialBounds)
-                          -> cres<'tcx, ty::ExistentialBounds>
+                          a: &ty::ExistentialBounds<'tcx>,
+                          b: &ty::ExistentialBounds<'tcx>)
+                          -> cres<'tcx, ty::ExistentialBounds<'tcx>>
     {
         let r = try!(self.contraregions(a.region_bound, b.region_bound));
         let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
+        let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
         Ok(ty::ExistentialBounds { region_bound: r,
-                                   builtin_bounds: nb })
+                                   builtin_bounds: nb,
+                                   projection_bounds: pb })
     }
 
     fn builtin_bounds(&self,
@@ -381,6 +427,16 @@ fn combine<C:Combine<'tcx>>(combiner: &C,
     }
 }
 
+impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn combine<C:Combine<'tcx>>(combiner: &C,
+                                a: &ty::ProjectionPredicate<'tcx>,
+                                b: &ty::ProjectionPredicate<'tcx>)
+                                -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
+    {
+        combiner.projection_predicates(a, b)
+    }
+}
+
 impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
     fn combine<C:Combine<'tcx>>(combiner: &C,
                                 a: &ty::FnSig<'tcx>,
@@ -496,7 +552,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
        &ty::ty_trait(ref b_)) => {
           debug!("Trying to match traits {} and {}", a, b);
           let principal = try!(this.binders(&a_.principal, &b_.principal));
-          let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds));
+          let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
           Ok(ty::mk_trait(tcx, principal, bounds))
       }
 
@@ -595,12 +651,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
       }
 
       (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
-          if a_data.item_name == b_data.item_name {
-              let trait_ref = try!(this.trait_refs(&*a_data.trait_ref, &*b_data.trait_ref));
-              Ok(ty::mk_projection(tcx, Rc::new(trait_ref), a_data.item_name))
-          } else {
-              Err(ty::terr_sorts(expected_found(this, a, b)))
-          }
+          let projection_ty = try!(this.projection_tys(a_data, b_data));
+          Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
       }
 
       _ => Err(ty::terr_sorts(expected_found(this, a, b)))
index 6b2ac04f5ce2ad982804a89f538499812ef029d9..e989f5a2cc2b44c9d71c9d900dbcf677732f2126 100644 (file)
@@ -396,14 +396,14 @@ pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Opti
     fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> {
         match autoref {
             &AutoUnsize(ref k) => match k {
-                &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-                    Some(mk_trait(cx, (*principal).clone(), bounds))
+                &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+                    Some(mk_trait(cx, principal.clone(), bounds.clone()))
                 }
                 _ => None
             },
             &AutoUnsizeUniq(ref k) => match k {
-                &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-                    Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds)))
+                &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+                    Some(mk_uniq(cx, mk_trait(cx, principal.clone(), bounds.clone())))
                 }
                 _ => None
             },
@@ -1040,7 +1040,7 @@ pub struct ClosureTy<'tcx> {
     pub unsafety: ast::Unsafety,
     pub onceness: ast::Onceness,
     pub store: TraitStore,
-    pub bounds: ExistentialBounds,
+    pub bounds: ExistentialBounds<'tcx>,
     pub sig: PolyFnSig<'tcx>,
     pub abi: abi::Abi,
 }
@@ -1376,7 +1376,7 @@ pub enum sty<'tcx> {
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct TyTrait<'tcx> {
     pub principal: ty::PolyTraitRef<'tcx>,
-    pub bounds: ExistentialBounds
+    pub bounds: ExistentialBounds<'tcx>,
 }
 
 impl<'tcx> TyTrait<'tcx> {
@@ -1510,7 +1510,9 @@ pub enum type_err<'tcx> {
     terr_builtin_bounds(expected_found<BuiltinBounds>),
     terr_variadic_mismatch(expected_found<bool>),
     terr_cyclic_ty,
-    terr_convergence_mismatch(expected_found<bool>)
+    terr_convergence_mismatch(expected_found<bool>),
+    terr_projection_name_mismatched(expected_found<ast::Name>),
+    terr_projection_bounds_length(expected_found<uint>),
 }
 
 /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
@@ -1528,10 +1530,11 @@ pub struct ParamBounds<'tcx> {
 /// major difference between this case and `ParamBounds` is that
 /// general purpose trait bounds are omitted and there must be
 /// *exactly one* region.
-#[deriving(Copy, PartialEq, Eq, Hash, Clone, Show)]
-pub struct ExistentialBounds {
+#[deriving(PartialEq, Eq, Hash, Clone, Show)]
+pub struct ExistentialBounds<'tcx> {
     pub region_bound: ty::Region,
-    pub builtin_bounds: BuiltinBounds
+    pub builtin_bounds: BuiltinBounds,
+    pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
 }
 
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
@@ -1559,9 +1562,10 @@ pub fn all_builtin_bounds() -> BuiltinBounds {
 }
 
 /// An existential bound that does not implement any traits.
-pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
+pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> {
     ty::ExistentialBounds { region_bound: r,
-                            builtin_bounds: empty_builtin_bounds() }
+                            builtin_bounds: empty_builtin_bounds(),
+                            projection_bounds: Vec::new() }
 }
 
 impl CLike for BuiltinBound {
@@ -1820,12 +1824,24 @@ pub struct ProjectionPredicate<'tcx> {
 
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
+impl<'tcx> PolyProjectionPredicate<'tcx> {
+    pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
+        self.0.projection_ty.sort_key()
+    }
+}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct ProjectionTy<'tcx> {
     pub trait_ref: Rc<ty::TraitRef<'tcx>>,
     pub item_name: ast::Name,
 }
 
+impl<'tcx> ProjectionTy<'tcx> {
+    pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
+        (self.trait_ref.def_id, self.item_name)
+    }
+}
+
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
@@ -2675,8 +2691,11 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
 
 pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
                       principal: ty::PolyTraitRef<'tcx>,
-                      bounds: ExistentialBounds)
-                      -> Ty<'tcx> {
+                      bounds: ExistentialBounds<'tcx>)
+                      -> Ty<'tcx>
+{
+    assert!(bound_list_is_sorted(bounds.projection_bounds.as_slice()));
+
     let inner = box TyTrait {
         principal: principal,
         bounds: bounds
@@ -2684,6 +2703,16 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
     mk_t(cx, ty_trait(inner))
 }
 
+fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
+    bounds.len() == 0 ||
+        bounds[1..].iter().enumerate().all(
+            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
+}
+
+pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
+    bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
+}
+
 pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>,
                            trait_ref: Rc<ty::TraitRef<'tcx>>,
                            item_name: ast::Name)
@@ -3226,7 +3255,7 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 }
             }
 
-            ty_trait(box TyTrait { bounds, .. }) => {
+            ty_trait(box TyTrait { ref bounds, .. }) => {
                 object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
             }
 
@@ -3391,7 +3420,7 @@ fn borrowed_contents(region: ty::Region,
     fn closure_contents(cty: &ClosureTy) -> TypeContents {
         // Closure contents are just like trait contents, but with potentially
         // even more stuff.
-        let st = object_contents(cty.bounds);
+        let st = object_contents(&cty.bounds);
 
         let st = match cty.store {
             UniqTraitStore => {
@@ -3405,7 +3434,7 @@ fn closure_contents(cty: &ClosureTy) -> TypeContents {
         st
     }
 
-    fn object_contents(bounds: ExistentialBounds) -> TypeContents {
+    fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
         // These are the type contents of the (opaque) interior. We
         // make no assumptions (other than that it cannot have an
         // in-scope type parameter within, which makes no sense).
@@ -4205,6 +4234,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                             let bounds = ty::ExistentialBounds {
                                 region_bound: ReStatic,
                                 builtin_bounds: all_builtin_bounds(),
+                                projection_bounds: vec!(),
                             };
 
                             ty::mk_closure(
@@ -4339,8 +4369,8 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
                                   format!("UnsizeStruct with bad sty: {}",
                                           ty_to_string(cx, ty))[])
         },
-        &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-            mk_trait(cx, (*principal).clone(), bounds)
+        &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+            mk_trait(cx, principal.clone(), bounds.clone())
         }
     }
 }
@@ -4760,6 +4790,16 @@ fn tstore_to_closure(s: &TraitStore) -> String {
                     if values.expected { "converging" } else { "diverging" },
                     if values.found { "converging" } else { "diverging" })
         }
+        terr_projection_name_mismatched(ref values) => {
+            format!("expected {}, found {}",
+                    token::get_name(values.expected),
+                    token::get_name(values.found))
+        }
+        terr_projection_bounds_length(ref values) => {
+            format!("expected {} associated type bindings, found {}",
+                    values.expected,
+                    values.found)
+        }
     }
 }
 
index 4ef597d21081e2a0fd0c246a9f45e3e5e4e81ed1..3aff69c0178469f380ecbd8b91276bafcf719c25 100644 (file)
@@ -121,8 +121,8 @@ fn fold_trait_store(&mut self, s: ty::TraitStore) -> ty::TraitStore {
         super_fold_trait_store(self, s)
     }
 
-    fn fold_existential_bounds(&mut self, s: ty::ExistentialBounds)
-                               -> ty::ExistentialBounds {
+    fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
+                               -> ty::ExistentialBounds<'tcx> {
         super_fold_existential_bounds(self, s)
     }
 
@@ -349,9 +349,9 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds {
-        folder.fold_existential_bounds(*self)
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
+        folder.fold_existential_bounds(self)
     }
 }
 
@@ -449,7 +449,7 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnsizeKind<'tcx>
         match *self {
             ty::UnsizeLength(len) => ty::UnsizeLength(len),
             ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n),
-            ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => {
+            ty::UnsizeVtable(ty::TyTrait{ref principal, ref bounds}, self_ty) => {
                 ty::UnsizeVtable(
                     ty::TyTrait {
                         principal: principal.fold_with(folder),
@@ -565,9 +565,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             let substs = substs.fold_with(this);
             ty::ty_enum(tid, this.tcx().mk_substs(substs))
         }
-        ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
+        ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
             ty::ty_trait(box ty::TyTrait {
-                principal: (*principal).fold_with(this),
+                principal: principal.fold_with(this),
                 bounds: bounds.fold_with(this),
             })
         }
@@ -693,12 +693,15 @@ pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
     }
 }
 
-pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
-                                                                bounds: ty::ExistentialBounds)
-                                                                -> ty::ExistentialBounds {
+pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
+    this: &mut T,
+    bounds: &ty::ExistentialBounds<'tcx>)
+    -> ty::ExistentialBounds<'tcx>
+{
     ty::ExistentialBounds {
         region_bound: bounds.region_bound.fold_with(this),
         builtin_bounds: bounds.builtin_bounds,
+        projection_bounds: bounds.projection_bounds.fold_with(this),
     }
 }
 
index 134a47225072d02bdc280e049f8d2bcb13cbb4ee..3e7b24ac93f9e5c314c0f8487b6c566f2c162d1d 100644 (file)
@@ -739,8 +739,8 @@ fn repr(&self, _tcx: &ctxt) -> String {
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ExistentialBounds {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         self.user_string(tcx)
     }
 }
@@ -1142,8 +1142,8 @@ fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::ExistentialBounds {
-    fn user_string(&self, tcx: &ctxt) -> String {
+impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
         if self.builtin_bounds.contains(&ty::BoundSend) &&
             self.region_bound == ty::ReStatic
         { // Region bound is implied by builtin bounds:
index 26959dfd1d524c1e68876dcb0581da8a30df84be..26fadb0dfb1020d7059990fbee8802ea2324c7a7 100644 (file)
@@ -810,11 +810,13 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     }
 }
 
+type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
+
 fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
                                    rscope: &RS,
                                    ty: &ast::Ty,
                                    bounds: &[ast::TyParamBound])
-                                   -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+                                   -> Result<TraitAndProjections<'tcx>, ErrorReported>
     where AC : AstConv<'tcx>, RS : RegionScope
 {
     /*!
@@ -832,14 +834,17 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
         ast::TyPath(ref path, id) => {
             match this.tcx().def_map.borrow().get(&id) {
                 Some(&def::DefTrait(trait_def_id)) => {
-                    // TODO do something with this
-                    let mut projections = Vec::new();
-                    Ok(ty::Binder(ast_path_to_trait_ref(this,
-                                                        rscope,
-                                                        trait_def_id,
-                                                        None,
-                                                        path,
-                                                        Some(&mut projections))))
+                    let mut projection_bounds = Vec::new();
+                    let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
+                                                                     rscope,
+                                                                     trait_def_id,
+                                                                     None,
+                                                                     path,
+                                                                     Some(&mut projection_bounds)));
+                    let projection_bounds = projection_bounds.into_iter()
+                                                             .map(ty::Binder)
+                                                             .collect();
+                    Ok((trait_ref, projection_bounds))
                 }
                 _ => {
                     span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
@@ -882,6 +887,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
                                         rscope: &RS,
                                         span: Span,
                                         trait_ref: ty::PolyTraitRef<'tcx>,
+                                        projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
                                         bounds: &[ast::TyParamBound])
                                         -> Ty<'tcx>
     where AC : AstConv<'tcx>, RS : RegionScope
@@ -890,6 +896,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
                                                      rscope,
                                                      span,
                                                      Some(trait_ref.clone()),
+                                                     projection_bounds,
                                                      bounds);
 
     let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
@@ -1019,9 +1026,9 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             }
             ast::TyObjectSum(ref ty, ref bounds) => {
                 match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) {
-                    Ok(trait_ref) => {
+                    Ok((trait_ref, projection_bounds)) => {
                         trait_ref_to_object_type(this, rscope, ast_ty.span,
-                                                 trait_ref, bounds[])
+                                                 trait_ref, projection_bounds, bounds[])
                     }
                     Err(ErrorReported) => {
                         this.tcx().types.err
@@ -1062,13 +1069,15 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                      rscope,
                                                      ast_ty.span,
                                                      None,
+                                                     Vec::new(),
                                                      f.bounds.as_slice());
+                let region_bound = bounds.region_bound;
                 let fn_decl = ty_of_closure(this,
                                             f.unsafety,
                                             f.onceness,
                                             bounds,
                                             ty::RegionTraitStore(
-                                                bounds.region_bound,
+                                                region_bound,
                                                 ast::MutMutable),
                                             &*f.decl,
                                             abi::Rust,
@@ -1092,15 +1101,19 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     def::DefTrait(trait_def_id) => {
                         // N.B. this case overlaps somewhat with
                         // TyObjectSum, see that fn for details
-                        let mut projections = Vec::new(); // TODO
+                        let mut projection_bounds = Vec::new();
                         let trait_ref = ast_path_to_trait_ref(this,
                                                               rscope,
                                                               trait_def_id,
                                                               None,
                                                               path,
-                                                              Some(&mut projections));
+                                                              Some(&mut projection_bounds));
                         let trait_ref = ty::Binder(trait_ref);
-                        trait_ref_to_object_type(this, rscope, path.span, trait_ref, &[])
+                        let projection_bounds = projection_bounds.into_iter()
+                                                                 .map(ty::Binder)
+                                                                 .collect();
+                        trait_ref_to_object_type(this, rscope, path.span,
+                                                 trait_ref, projection_bounds, &[])
                     }
                     def::DefTy(did, _) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
@@ -1437,7 +1450,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
     this: &AC,
     unsafety: ast::Unsafety,
     onceness: ast::Onceness,
-    bounds: ty::ExistentialBounds,
+    bounds: ty::ExistentialBounds<'tcx>,
     store: ty::TraitStore,
     decl: &ast::FnDecl,
     abi: abi::Abi,
@@ -1500,14 +1513,15 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
     rscope: &RS,
     span: Span,
     principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
     ast_bounds: &[ast::TyParamBound])
-    -> ty::ExistentialBounds
+    -> ty::ExistentialBounds<'tcx>
 {
     let partitioned_bounds =
         partition_bounds(this.tcx(), span, ast_bounds);
 
     conv_existential_bounds_from_partitioned_bounds(
-        this, rscope, span, principal_trait_ref, partitioned_bounds)
+        this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
 }
 
 fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
@@ -1520,14 +1534,14 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
 {
     let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
 
-    let mut projections = Vec::new();
+    let mut projection_bounds = Vec::new();
     let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
         Some(trait_bound) => {
             let ptr = instantiate_poly_trait_ref(this,
                                                  rscope,
                                                  trait_bound,
                                                  None,
-                                                 &mut projections);
+                                                 &mut projection_bounds);
             Some(ptr)
         }
         None => {
@@ -1538,13 +1552,12 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
         }
     };
 
-    // TODO use projections somewhere
-
     let bounds =
         conv_existential_bounds_from_partitioned_bounds(this,
                                                         rscope,
                                                         span,
                                                         main_trait_bound.clone(),
+                                                        projection_bounds,
                                                         partitioned_bounds);
 
     match main_trait_bound {
@@ -1558,8 +1571,9 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
     rscope: &RS,
     span: Span,
     principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    mut projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
     partitioned_bounds: PartitionedBounds)
-    -> ty::ExistentialBounds
+    -> ty::ExistentialBounds<'tcx>
     where AC: AstConv<'tcx>, RS:RegionScope
 {
     let PartitionedBounds { builtin_bounds,
@@ -1582,9 +1596,12 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
                                             principal_trait_ref,
                                             builtin_bounds);
 
+    ty::sort_bounds_list(projection_bounds.as_mut_slice());
+
     ty::ExistentialBounds {
         region_bound: region_bound,
         builtin_bounds: builtin_bounds,
+        projection_bounds: projection_bounds,
     }
 }
 
index fbc6d49d6e9a87e65579c2ba0a93f0ac83cf0727..e737bb1b237fb87dd48a7c6b3ab99ab5b0eb9579 100644 (file)
@@ -15,7 +15,6 @@
 use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
 use syntax::ast;
 use syntax::codemap::Span;
-use std::rc::Rc;
 
 pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                 fulfillment_cx: &mut FulfillmentContext<'tcx>,
index ec964ab638f14296ed353e5353b5e6a06adb8599..19108ca710bc1a3153f3877794cfe81329aa1140 100644 (file)
@@ -289,7 +289,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                 (&ty::UniqTraitStore, _) => ast::Once,
                 (&ty::RegionTraitStore(..), _) => ast::Many,
             };
-            (Some(sig), onceness, cenv.bounds)
+            (Some(sig), onceness, cenv.bounds.clone())
         }
         _ => {
             // Not an error! Means we're inferring the closure type
index b8cf215f89eeca4e57dc9a66409c7a8df54d96a9..1da8852c9b23c827989d4efbc61b57443bbd8cb6 100644 (file)
@@ -768,7 +768,7 @@ fn walk_cast<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
             }
 
             /*From:*/ (_,
-            /*To:  */  &ty::ty_trait(box ty::TyTrait { bounds, .. })) => {
+            /*To:  */  &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => {
                 // When T is existentially quantified as a trait
                 // `Foo+'to`, it must outlive the region bound `'to`.
                 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
@@ -851,7 +851,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     }
 
     match function_type.sty {
-        ty::ty_closure(box ty::ClosureTy {bounds, ..}) => {
+        ty::ty_closure(box ty::ClosureTy {ref bounds, ..}) => {
             ty::with_freevars(tcx, expr.id, |freevars| {
                 ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
             })
@@ -859,7 +859,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
         ty::ty_unboxed_closure(_, region, _) => {
             ty::with_freevars(tcx, expr.id, |freevars| {
                 let bounds = ty::region_existential_bound(*region);
-                ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
+                ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars);
             })
         }
         _ => {}
@@ -870,7 +870,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     /// over values outliving the object's lifetime bound.
     fn ensure_free_variable_types_outlive_closure_bound(
         rcx: &mut Rcx,
-        bounds: ty::ExistentialBounds,
+        bounds: &ty::ExistentialBounds,
         expr: &ast::Expr,
         freevars: &[ty::Freevar])
     {
index 98badf9c049963f7a7d2b9c8af17711280b3a470..5cf759a4dce666f410606c50e115b7ae1b5741ad 100644 (file)
@@ -244,7 +244,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let object_trait_ty =
         ty::mk_trait(fcx.tcx(),
                      object_trait.principal.clone(),
-                     object_trait.bounds);
+                     object_trait.bounds.clone());
 
     debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
            referent_ty.repr(fcx.tcx()),
index d5ffce8db78f890de988896bec7bd87411ad46e0..5063ce36019d11a9acae951ac9a0b1f03e9f43f7 100644 (file)
@@ -500,13 +500,14 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
     }
 }
 
-impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
+impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
     fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
         let mut vec = vec![];
         self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
         for bb in self.builtin_bounds.iter() {
             vec.push(bb.clean(cx));
         }
+        // TODO projection bounds
         vec
     }
 }
@@ -1441,18 +1442,11 @@ fn clean(&self, cx: &DocContext) -> Type {
                 }
             }
             ty::ty_struct(did, substs) |
-            ty::ty_enum(did, substs) |
-            ty::ty_trait(box ty::TyTrait {
-                principal: ty::Binder(ty::TraitRef { def_id: did, substs }),
-                .. }) =>
-            {
+            ty::ty_enum(did, substs) => {
                 let fqn = csearch::get_item_path(cx.tcx(), did);
-                let fqn: Vec<String> = fqn.into_iter().map(|i| {
-                    i.to_string()
-                }).collect();
+                let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
                 let kind = match self.sty {
                     ty::ty_struct(..) => TypeStruct,
-                    ty::ty_trait(..) => TypeTrait,
                     _ => TypeEnum,
                 };
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
@@ -1464,11 +1458,24 @@ fn clean(&self, cx: &DocContext) -> Type {
                     did: did,
                 }
             }
+            ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+                let did = principal.def_id();
+                let fqn = csearch::get_item_path(cx.tcx(), did);
+                let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
+                let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
+                                         Some(did), principal.substs());
+                cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
+                ResolvedPath {
+                    path: path,
+                    typarams: Some(bounds.clean(cx)),
+                    did: did,
+                }
+            }
             ty::ty_tup(ref t) => Tuple(t.clean(cx)),
 
             ty::ty_projection(ref data) => {
                 let trait_ref = match data.trait_ref.clean(cx) {
-                    TyParamBound::TraitBound(t) => t,
+                    TyParamBound::TraitBound(t) => t.trait_,
                     TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
                 };
                 Type::QPath {