]> git.lizzy.rs Git - rust.git/commitdiff
Convert TyPolyTraitRef to accept arbitary bounds, so that things like
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 15 Nov 2014 21:55:27 +0000 (16:55 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 18 Nov 2014 17:32:37 +0000 (12:32 -0500)
`Box<for<'a> Foo<&'a T> + 'a>` can be accepted. Also cleanup the visitor/fold
in general, exposing more callbacks.

src/librustc/middle/resolve.rs
src/librustc/middle/typeck/astconv.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs

index 94b52532a946d63e1d346b128fe815e26e777b18..baf53cc34ba94bded0b8fa304f13663e15ad8621 100644 (file)
@@ -5038,10 +5038,10 @@ fn resolve_type(&mut self, ty: &Ty) {
                 visit::walk_ty(self, ty);
             }
 
-            TyPolyTraitRef(ref poly_trait_ref) => {
-                self.resolve_poly_trait_reference(
+            TyPolyTraitRef(ref bounds) => {
+                self.resolve_type_parameter_bounds(
                     ty.id,
-                    &**poly_trait_ref,
+                    bounds,
                     TraitObject);
                 visit::walk_ty(self, ty);
             }
index 082b2acd1d88cd2c574255b49e947b72247e462c..d85f8eab7cd07dcab60032219b1924fb4893ad8b 100644 (file)
@@ -883,15 +883,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 
                 ty::mk_closure(tcx, fn_decl)
             }
-            ast::TyPolyTraitRef(ref data) => {
-                // FIXME(#18639) this is just a placeholder for code to come
-                let principal = instantiate_trait_ref(this, rscope, &data.trait_ref, None, None);
-                let bounds = conv_existential_bounds(this,
-                                                     rscope,
-                                                     ast_ty.span,
-                                                     &[principal.clone()],
-                                                     &[]);
-                ty::mk_trait(tcx, (*principal).clone(), bounds)
+            ast::TyPolyTraitRef(ref bounds) => {
+                conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds.as_slice())
             }
             ast::TyPath(ref path, ref bounds, id) => {
                 let a_def = match tcx.def_map.borrow().get(&id) {
@@ -1371,15 +1364,66 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
     let ast_bound_refs: Vec<&ast::TyParamBound> =
         ast_bounds.iter().collect();
 
+    let partitioned_bounds =
+        partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
+
+    conv_existential_bounds_from_partitioned_bounds(
+        this, rscope, span, main_trait_refs, partitioned_bounds)
+}
+
+fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
+    this: &AC,
+    rscope: &RS,
+    span: Span,
+    ast_bounds: &[ast::TyParamBound])
+    -> ty::t
+    where AC: AstConv<'tcx>, RS:RegionScope
+{
+    let ast_bounds: Vec<&ast::TyParamBound> = ast_bounds.iter().collect();
+    let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
+
+    let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
+        Some(trait_bound) => {
+            Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
+        }
+        None => {
+            this.tcx().sess.span_err(
+                span,
+                "at least one non-builtin trait is required for an object type");
+            None
+        }
+    };
+
+    let bounds = conv_existential_bounds_from_partitioned_bounds(this,
+                                                                 rscope,
+                                                                 span,
+                                                                 main_trait_bound.as_slice(),
+                                                                 partitioned_bounds);
+
+    match main_trait_bound {
+        None => ty::mk_err(),
+        Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
+    }
+}
+
+pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
+    this: &AC,
+    rscope: &RS,
+    span: Span,
+    main_trait_refs: &[Rc<ty::TraitRef>],
+    partitioned_bounds: PartitionedBounds)
+    -> ty::ExistentialBounds
+    where AC: AstConv<'tcx>, RS:RegionScope
+{
     let PartitionedBounds { builtin_bounds,
                             trait_bounds,
                             region_bounds } =
-        partition_bounds(this.tcx(), span, ast_bound_refs.as_slice());
+        partitioned_bounds;
 
     if !trait_bounds.is_empty() {
         let b = &trait_bounds[0];
         this.tcx().sess.span_err(
-            b.path.span,
+            b.trait_ref.path.span,
             format!("only the builtin traits can be used \
                      as closure or object bounds").as_slice());
     }
index 0cb80d4c153970735759f84a97396020aa5cd6e5..15e14902727f5db6e4dff09d7e143b57a430bdc3 100644 (file)
@@ -1154,7 +1154,7 @@ pub enum Ty_ {
     /// Type parameters are stored in the Path itself
     TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
     /// A type like `for<'a> Foo<&'a Bar>`
-    TyPolyTraitRef(P<PolyTraitRef>),
+    TyPolyTraitRef(TyParamBounds),
     /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
     TyQPath(P<QPath>),
     /// No-op; kept solely so that we can pretty-print faithfully
index 2e3a15bfd4b4b1826a8cdb654718d04faf380779..30cdecbc851999877562f804c51d37822e1f7196 100644 (file)
@@ -494,10 +494,10 @@ fn visit_fn(&mut self,
         }
 
         visit::walk_fn(self,
-                        function_kind,
-                        function_declaration,
-                        block,
-                        span);
+                       function_kind,
+                       function_declaration,
+                       block,
+                       span);
 
         if !self.pass_through_items {
             match function_kind {
index 56d912824374d7ae025fab3c1e42ea375d732755..b3137ff5f7e52c0acd00cac02a9b748dfffcade9 100644 (file)
@@ -445,10 +445,12 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyFixedLengthVec(ty, e) => {
                 TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
             }
-            TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
-            TyPolyTraitRef(poly_trait_ref) => {
-                TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p)))
-            },
+            TyTypeof(expr) => {
+                TyTypeof(fld.fold_expr(expr))
+            }
+            TyPolyTraitRef(bounds) => {
+                TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+            }
         },
         span: fld.new_span(span)
     })
index 98479d65cbb2fb0579e5a352b2208311047f2ff9..40c4ac9f8c04418fa2b1a811fcf2dfaff73e9ee5 100644 (file)
@@ -1023,10 +1023,21 @@ pub fn parse_for_in_type(&mut self) -> Ty_ {
             self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
         } else if self.token == token::ModSep ||
                   self.token.is_ident() ||
-                  self.token.is_path() {
+                  self.token.is_path()
+        {
             let trait_ref = self.parse_trait_ref();
-            TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs,
-                                            trait_ref: trait_ref }))
+            let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
+                                                     trait_ref: trait_ref };
+            let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
+                self.parse_ty_param_bounds()
+            } else {
+                OwnedSlice::empty()
+            };
+            let all_bounds =
+                Some(TraitTyParamBound(poly_trait_ref)).into_iter()
+                .chain(other_bounds.into_vec().into_iter())
+                .collect();
+            ast::TyPolyTraitRef(all_bounds)
         } else {
             self.parse_ty_closure(lifetime_defs)
         }
index 0543b80f208b1073c7bb8d9f9ad92f77cb8ff654..e6e0c33a42dbdf0497ddb841ba33f3d09cacf429 100644 (file)
@@ -739,8 +739,8 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
             ast::TyPath(ref path, ref bounds, _) => {
                 try!(self.print_bounded_path(path, bounds));
             }
-            ast::TyPolyTraitRef(ref poly_trait_ref) => {
-                try!(self.print_poly_trait_ref(&**poly_trait_ref));
+            ast::TyPolyTraitRef(ref bounds) => {
+                try!(self.print_bounds("", bounds));
             }
             ast::TyQPath(ref qpath) => {
                 try!(word(&mut self.s, "<"));
index 2960c28a8b71de6d2f86cc75c5cdbbfc15f9aa61..efe1e18eda92872d6b2800373a4e64034cb45727 100644 (file)
@@ -78,6 +78,9 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _:
     fn visit_ty_method(&mut self, t: &'v TypeMethod) { walk_ty_method(self, t) }
     fn visit_trait_item(&mut self, t: &'v TraitItem) { walk_trait_item(self, t) }
     fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
+    fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
+        walk_ty_param_bound(self, bounds)
+    }
     fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
         walk_poly_trait_ref(self, t)
     }
@@ -119,6 +122,12 @@ fn visit_mac(&mut self, _macro: &'v Mac) {
     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
         walk_path(self, path)
     }
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
+        walk_path_segment(self, path_span, path_segment)
+    }
+    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
+        walk_path_parameters(self, path_span, path_parameters)
+    }
     fn visit_attribute(&mut self, _attr: &'v Attribute) {}
 }
 
@@ -170,7 +179,7 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
                 ViewPathGlob(ref path, id) => {
                     visitor.visit_path(path, id);
                 }
-                ViewPathList(ref path, ref list, _) => {
+                ViewPathList(ref prefix, ref list, _) => {
                     for id in list.iter() {
                         match id.node {
                             PathListIdent { name, .. } => {
@@ -179,7 +188,10 @@ pub fn walk_view_item<'v, V: Visitor<'v>>(visitor: &mut V, vi: &'v ViewItem) {
                             PathListMod { .. } => ()
                         }
                     }
-                    walk_path(visitor, path);
+
+                    // Note that the `prefix` here is not a complete
+                    // path, so we don't use `visit_path`.
+                    walk_path(visitor, prefix);
                 }
             }
         }
@@ -212,7 +224,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
                                          trait_ref: &'v PolyTraitRef)
     where V: Visitor<'v>
 {
-    walk_lifetime_decls(visitor, &trait_ref.bound_lifetimes);
+    walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
     visitor.visit_trait_ref(&trait_ref.trait_ref);
 }
 
@@ -290,7 +302,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
         }
         ItemTrait(ref generics, _, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
-            walk_ty_param_bounds(visitor, bounds);
+            walk_ty_param_bounds_helper(visitor, bounds);
             for method in methods.iter() {
                 visitor.visit_trait_item(method)
             }
@@ -363,29 +375,29 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
                 visitor.visit_ty(&*argument.ty)
             }
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_ty_param_bounds(visitor, &function_declaration.bounds);
-            walk_lifetime_decls(visitor, &function_declaration.lifetimes);
+            walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
+            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
         TyProc(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
             }
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_ty_param_bounds(visitor, &function_declaration.bounds);
-            walk_lifetime_decls(visitor, &function_declaration.lifetimes);
+            walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
+            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
         TyBareFn(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)
             }
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_lifetime_decls(visitor, &function_declaration.lifetimes);
+            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
         TyPath(ref path, ref opt_bounds, id) => {
             visitor.visit_path(path, id);
             match *opt_bounds {
                 Some(ref bounds) => {
-                    walk_ty_param_bounds(visitor, bounds);
+                    walk_ty_param_bounds_helper(visitor, bounds);
                 }
                 None => { }
             }
@@ -399,8 +411,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             visitor.visit_ty(&**ty);
             visitor.visit_expr(&**expression)
         }
-        TyPolyTraitRef(ref poly_trait_ref) => {
-            visitor.visit_poly_trait_ref(&**poly_trait_ref)
+        TyPolyTraitRef(ref bounds) => {
+            walk_ty_param_bounds_helper(visitor, bounds)
         }
         TyTypeof(ref expression) => {
             visitor.visit_expr(&**expression)
@@ -409,8 +421,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     }
 }
 
-fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V,
-                                           lifetimes: &'v Vec<LifetimeDef>) {
+pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                      lifetimes: &'v Vec<LifetimeDef>) {
     for l in lifetimes.iter() {
         visitor.visit_lifetime_decl(l);
     }
@@ -418,24 +430,35 @@ fn walk_lifetime_decls<'v, V: Visitor<'v>>(visitor: &mut V,
 
 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     for segment in path.segments.iter() {
-        visitor.visit_ident(path.span, segment.identifier);
+        visitor.visit_path_segment(path.span, segment);
+    }
+}
 
-        match segment.parameters {
-            ast::AngleBracketedParameters(ref data) => {
-                for typ in data.types.iter() {
-                    visitor.visit_ty(&**typ);
-                }
-                for lifetime in data.lifetimes.iter() {
-                    visitor.visit_lifetime_ref(lifetime);
-                }
+pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             path_span: Span,
+                                             segment: &'v PathSegment) {
+    visitor.visit_ident(path_span, segment.identifier);
+    visitor.visit_path_parameters(path_span, &segment.parameters);
+}
+
+pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                _path_span: Span,
+                                                path_parameters: &'v PathParameters) {
+    match *path_parameters {
+        ast::AngleBracketedParameters(ref data) => {
+            for typ in data.types.iter() {
+                visitor.visit_ty(&**typ);
             }
-            ast::ParenthesizedParameters(ref data) => {
-                for typ in data.inputs.iter() {
-                    visitor.visit_ty(&**typ);
-                }
-                for typ in data.output.iter() {
-                    visitor.visit_ty(&**typ);
-                }
+            for lifetime in data.lifetimes.iter() {
+                visitor.visit_lifetime_ref(lifetime);
+            }
+        }
+        ast::ParenthesizedParameters(ref data) => {
+            for typ in data.inputs.iter() {
+                visitor.visit_ty(&**typ);
+            }
+            for typ in data.output.iter() {
+                visitor.visit_ty(&**typ);
             }
         }
     }
@@ -511,32 +534,37 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
     }
 }
 
-pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                bounds: &'v OwnedSlice<TyParamBound>) {
+pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                       bounds: &'v OwnedSlice<TyParamBound>) {
     for bound in bounds.iter() {
-        match *bound {
-            TraitTyParamBound(ref typ) => {
-                visitor.visit_poly_trait_ref(typ)
-            }
-            RegionTyParamBound(ref lifetime) => {
-                visitor.visit_lifetime_ref(lifetime);
-            }
+        visitor.visit_ty_param_bound(bound)
+    }
+}
+
+pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
+                                               bound: &'v TyParamBound) {
+    match *bound {
+        TraitTyParamBound(ref typ) => {
+            visitor.visit_poly_trait_ref(typ);
+        }
+        RegionTyParamBound(ref lifetime) => {
+            visitor.visit_lifetime_ref(lifetime);
         }
     }
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
     for type_parameter in generics.ty_params.iter() {
-        walk_ty_param_bounds(visitor, &type_parameter.bounds);
+        walk_ty_param_bounds_helper(visitor, &type_parameter.bounds);
         match type_parameter.default {
             Some(ref ty) => visitor.visit_ty(&**ty),
             None => {}
         }
     }
-    walk_lifetime_decls(visitor, &generics.lifetimes);
+    walk_lifetime_decls_helper(visitor, &generics.lifetimes);
     for predicate in generics.where_clause.predicates.iter() {
         visitor.visit_ident(predicate.span, predicate.ident);
-        walk_ty_param_bounds(visitor, &predicate.bounds);
+        walk_ty_param_bounds_helper(visitor, &predicate.bounds);
     }
 }