about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-11-07 06:53:45 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-11-07 15:51:30 -0500
commit244231720d29db856c5a28c0dda6c2efd7c9219a (patch)
tree41648e7c6c16102a7a602be441b4f1cdad8e7411 /src/libsyntax
parentc18a1327e3ccf02ae9f755ca280d53177eeb298d (diff)
downloadrust-244231720d29db856c5a28c0dda6c2efd7c9219a.tar.gz
rust-244231720d29db856c5a28c0dda6c2efd7c9219a.zip
Update parser with `for` syntax
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs20
-rw-r--r--src/libsyntax/ast_map/mod.rs2
-rw-r--r--src/libsyntax/ext/build.rs15
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs4
-rw-r--r--src/libsyntax/fold.rs24
-rw-r--r--src/libsyntax/parse/parser.rs310
-rw-r--r--src/libsyntax/print/pprust.rs31
-rw-r--r--src/libsyntax/visit.rs29
8 files changed, 261 insertions, 174 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 20f7caac482..145978bb73f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -307,7 +307,7 @@ pub const DUMMY_NODE_ID: NodeId = -1;
 /// detects Copy, Send and Sync.
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum TyParamBound {
-    TraitTyParamBound(TraitRef),
+    TraitTyParamBound(PolyTraitRef),
     RegionTyParamBound(Lifetime)
 }
 
@@ -318,7 +318,7 @@ pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
     pub bounds: TyParamBounds,
-    pub unbound: Option<TyParamBound>,
+    pub unbound: Option<TraitRef>,
     pub default: Option<P<Ty>>,
     pub span: Span
 }
@@ -1097,6 +1097,7 @@ pub enum Ty_ {
     TyBareFn(P<BareFnTy>),
     TyTup(Vec<P<Ty>> ),
     TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
+    TyPolyTraitRef(P<PolyTraitRef>), // a type like `for<'a> Foo<&'a Bar>`
     /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
     TyQPath(P<QPath>),
     /// No-op; kept solely so that we can pretty-print faithfully
@@ -1350,7 +1351,6 @@ pub struct Attribute_ {
     pub is_sugared_doc: bool,
 }
 
-
 /// TraitRef's appear in impls.
 /// resolve maps each TraitRef's ref_id to its defining trait; that's all
 /// that the ref_id is for. The impl_id maps to the "self type" of this impl.
@@ -1360,7 +1360,15 @@ pub struct Attribute_ {
 pub struct TraitRef {
     pub path: Path,
     pub ref_id: NodeId,
-    pub lifetimes: Vec<LifetimeDef>,
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub struct PolyTraitRef {
+    /// The `'a` in `<'a> Foo<&'a T>`
+    pub bound_lifetimes: Vec<LifetimeDef>,
+
+    /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
+    pub trait_ref: TraitRef
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
@@ -1448,8 +1456,8 @@ pub enum Item_ {
     ItemStruct(P<StructDef>, Generics),
     /// Represents a Trait Declaration
     ItemTrait(Generics,
-              Option<TyParamBound>, // (optional) default bound not required for Self.
-                                    // Currently, only Sized makes sense here.
+              Option<TraitRef>, // (optional) default bound not required for Self.
+                                // Currently, only Sized makes sense here.
               TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Generics,
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 3adb062864e..d65be4c45e8 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -770,7 +770,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                 for b in bounds.iter() {
                     match *b {
                         TraitTyParamBound(ref t) => {
-                            self.insert(t.ref_id, NodeItem(i));
+                            self.insert(t.trait_ref.ref_id, NodeItem(i));
                         }
                         _ => {}
                     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5921d630b89..862cbf3d7ca 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -68,10 +68,11 @@ pub trait AstBuilder {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TyParamBound>,
+               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam;
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
+    fn poly_trait_ref(&self, path: ast::Path) -> ast::PolyTraitRef;
     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
     fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
     fn lifetime_def(&self,
@@ -417,7 +418,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TyParamBound>,
+               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam {
         ast::TyParam {
             ident: id,
@@ -445,12 +446,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::TraitRef {
             path: path,
             ref_id: ast::DUMMY_NODE_ID,
-            lifetimes: Vec::new(),
+        }
+    }
+
+    fn poly_trait_ref(&self, path: ast::Path) -> ast::PolyTraitRef {
+        ast::PolyTraitRef {
+            bound_lifetimes: Vec::new(),
+            trait_ref: self.trait_ref(path)
         }
     }
 
     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
-        ast::TraitTyParamBound(self.trait_ref(path))
+        ast::TraitTyParamBound(self.poly_trait_ref(path))
     }
 
     fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index a90618a30b6..1ec1e3b1224 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -194,7 +194,7 @@ impl<'a> Ty<'a> {
 
 
 fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
-               bounds: &[Path], unbound: Option<ast::TyParamBound>,
+               bounds: &[Path], unbound: Option<ast::TraitRef>,
                self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
     let bounds =
         bounds.iter().map(|b| {
@@ -220,7 +220,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
 #[deriving(Clone)]
 pub struct LifetimeBounds<'a> {
     pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
-    pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
+    pub bounds: Vec<(&'a str, Option<ast::TraitRef>, Vec<Path<'a>>)>,
 }
 
 impl<'a> LifetimeBounds<'a> {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 2074a6bfab9..85d4e157b7b 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -227,6 +227,10 @@ pub trait Folder {
         noop_fold_trait_ref(p, self)
     }
 
+    fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef {
+        noop_fold_poly_trait_ref(p, self)
+    }
+
     fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
         noop_fold_struct_def(struct_def, self)
     }
@@ -442,7 +446,10 @@ 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))
+            TyTypeof(expr) => TyTypeof(fld.fold_expr(expr)),
+            TyPolyTraitRef(poly_trait_ref) => {
+                TyPolyTraitRef(poly_trait_ref.map(|p| fld.fold_poly_trait_ref(p)))
+            },
         },
         span: fld.new_span(span)
     })
@@ -711,7 +718,7 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
                                    -> TyParamBound
                                    where T: Folder {
     match tpb {
-        TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
+        TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_poly_trait_ref(ty)),
         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
     }
 }
@@ -722,7 +729,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
         id: fld.new_id(id),
         ident: ident,
         bounds: fld.fold_bounds(bounds),
-        unbound: unbound.map(|x| fld.fold_ty_param_bound(x)),
+        unbound: unbound.map(|x| fld.fold_trait_ref(x)),
         default: default.map(|x| fld.fold_ty(x)),
         span: span
     }
@@ -842,13 +849,18 @@ pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
     let id = fld.new_id(p.ref_id);
     let TraitRef {
         path,
-        lifetimes,
-        ..
+        ref_id: _,
     } = p;
     ast::TraitRef {
         path: fld.fold_path(path),
         ref_id: id,
-        lifetimes: fld.fold_lifetime_defs(lifetimes),
+    }
+}
+
+pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
+    ast::PolyTraitRef {
+        bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
+        trait_ref: fld.fold_trait_ref(p.trait_ref)
     }
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9ba11d63da5..6873c015fd5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -42,6 +42,7 @@ use ast::{Method, MutTy, BiMul, Mutability};
 use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
 use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
+use ast::{PolyTraitRef};
 use ast::{QPath, RequiredMethod};
 use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
@@ -53,7 +54,7 @@ use ast::{TtDelimited, TtSequence, TtToken};
 use ast::{TupleVariantKind, Ty, Ty_, TyBot};
 use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
+use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
 use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
 use ast::{UnnamedField, UnsafeBlock};
@@ -968,30 +969,14 @@ impl<'a> Parser<'a> {
     /// Is the current token one of the keywords that signals a bare function
     /// type?
     pub fn token_is_bare_fn_keyword(&mut self) -> bool {
-        if self.token.is_keyword(keywords::Fn) {
-            return true
-        }
-
-        if self.token.is_keyword(keywords::Unsafe) ||
-            self.token.is_keyword(keywords::Once) {
-            return self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
-        }
-
-        false
+        self.token.is_keyword(keywords::Fn) ||
+            self.token.is_keyword(keywords::Unsafe) ||
+            self.token.is_keyword(keywords::Extern)
     }
 
     /// Is the current token one of the keywords that signals a closure type?
     pub fn token_is_closure_keyword(&mut self) -> bool {
-        self.token.is_keyword(keywords::Unsafe) ||
-            self.token.is_keyword(keywords::Once)
-    }
-
-    /// Is the current token one of the keywords that signals an old-style
-    /// closure type (with explicit sigil)?
-    pub fn token_is_old_style_closure_keyword(&mut self) -> bool {
-        self.token.is_keyword(keywords::Unsafe) ||
-            self.token.is_keyword(keywords::Once) ||
-            self.token.is_keyword(keywords::Fn)
+        self.token.is_keyword(keywords::Unsafe)
     }
 
     pub fn get_lifetime(&mut self) -> ast::Ident {
@@ -1001,8 +986,57 @@ impl<'a> Parser<'a> {
         }
     }
 
+    pub fn parse_for_in_type(&mut self) -> Ty_ {
+        /*
+        Parses whatever can come after a `for` keyword in a type.
+        The `for` has already been consumed.
+
+        Deprecated:
+
+        - for <'lt> |S| -> T
+        - for <'lt> proc(S) -> T
+
+        Eventually:
+
+        - for <'lt> [unsafe] [extern "ABI"] fn (S) -> T
+        - for <'lt> path::foo(a, b)
+
+        */
+
+        // parse <'lt>
+        let lifetime_defs = self.parse_late_bound_lifetime_defs();
+
+        // examine next token to decide to do
+        if self.eat_keyword(keywords::Proc) {
+            self.parse_proc_type(lifetime_defs)
+        } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() {
+            self.parse_ty_bare_fn_or_ty_closure(lifetime_defs)
+        } else if self.token == token::ModSep ||
+                  self.token.is_ident() ||
+                  self.token.is_path() {
+            let trait_ref = self.parse_trait_ref();
+            TyPolyTraitRef(P(PolyTraitRef { bound_lifetimes: lifetime_defs,
+                                            trait_ref: trait_ref }))
+        } else {
+            self.parse_ty_closure(lifetime_defs)
+        }
+    }
+
+    pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ {
+        let mode = if plus_allowed {
+            LifetimeAndTypesAndBounds
+        } else {
+            LifetimeAndTypesWithoutColons
+        };
+        let PathAndBounds {
+            path,
+            bounds
+        } = self.parse_path(mode);
+        TyPath(path, bounds, ast::DUMMY_NODE_ID)
+    }
+
     /// parse a TyBareFn type:
-    pub fn parse_ty_bare_fn(&mut self) -> Ty_ {
+    pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
         /*
 
         [unsafe] [extern "ABI"] fn <'lt> (S) -> T
@@ -1023,18 +1057,26 @@ impl<'a> Parser<'a> {
         };
 
         self.expect_keyword(keywords::Fn);
-        let (decl, lifetimes) = self.parse_ty_fn_decl(true);
+        let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
+        let (inputs, variadic) = self.parse_fn_args(false, true);
+        let (ret_style, ret_ty) = self.parse_ret_ty();
+        let decl = P(FnDecl {
+            inputs: inputs,
+            output: ret_ty,
+            cf: ret_style,
+            variadic: variadic
+        });
         TyBareFn(P(BareFnTy {
             abi: abi,
             fn_style: fn_style,
-            lifetimes: lifetimes,
+            lifetimes: lifetime_defs,
             decl: decl
         }))
     }
 
     /// Parses a procedure type (`proc`). The initial `proc` keyword must
     /// already have been parsed.
-    pub fn parse_proc_type(&mut self) -> Ty_ {
+    pub fn parse_proc_type(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
         /*
 
         proc <'lt> (S) [:Bounds] -> T
@@ -1043,19 +1085,12 @@ impl<'a> Parser<'a> {
          |     |    |      |      Return type
          |     |    |    Bounds
          |     |  Argument types
-         |   Lifetimes
+         |   Legacy lifetimes
         the `proc` keyword
 
         */
 
-        let lifetime_defs = if self.eat(&token::Lt) {
-            let lifetime_defs = self.parse_lifetime_defs();
-            self.expect_gt();
-            lifetime_defs
-        } else {
-            Vec::new()
-        };
-
+        let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
         let (inputs, variadic) = self.parse_fn_args(false, false);
         let bounds = self.parse_colon_then_ty_param_bounds();
         let (ret_style, ret_ty) = self.parse_ret_ty();
@@ -1100,33 +1135,49 @@ impl<'a> Parser<'a> {
         return None
     }
 
+    pub fn parse_ty_bare_fn_or_ty_closure(&mut self, lifetime_defs: Vec<LifetimeDef>) -> Ty_ {
+        // Both bare fns and closures can begin with stuff like unsafe
+        // and extern. So we just scan ahead a few tokens to see if we see
+        // a `fn`.
+        //
+        // Closure:  [unsafe] <'lt> |S| [:Bounds] -> T
+        // Fn:       [unsafe] [extern "ABI"] fn <'lt> (S) -> T
+
+        if self.token.is_keyword(keywords::Fn) {
+            self.parse_ty_bare_fn(lifetime_defs)
+        } else if self.token.is_keyword(keywords::Extern) {
+            self.parse_ty_bare_fn(lifetime_defs)
+        } else if self.token.is_keyword(keywords::Unsafe) {
+            if self.look_ahead(1, |t| t.is_keyword(keywords::Fn) ||
+                                      t.is_keyword(keywords::Extern)) {
+                self.parse_ty_bare_fn(lifetime_defs)
+            } else {
+                self.parse_ty_closure(lifetime_defs)
+            }
+        } else {
+            self.parse_ty_closure(lifetime_defs)
+        }
+    }
+
     /// Parse a TyClosure type
-    pub fn parse_ty_closure(&mut self) -> Ty_ {
+    pub fn parse_ty_closure(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
         /*
 
-        [unsafe] [once] <'lt> |S| [:Bounds] -> T
-        ^~~~~~~^ ^~~~~^ ^~~~^  ^  ^~~~~~~~^    ^
-          |        |      |    |      |        |
-          |        |      |    |      |      Return type
-          |        |      |    |  Closure bounds
-          |        |      |  Argument types
-          |        |    Lifetime defs
-          |     Once-ness (a.k.a., affine)
+        [unsafe] <'lt> |S| [:Bounds] -> T
+        ^~~~~~~^ ^~~~^  ^  ^~~~~~~~^    ^
+          |        |       |      |        |
+          |        |       |      |      Return type
+          |        |       |  Closure bounds
+          |        |     Argument types
+          |      Deprecated lifetime defs
+          |
         Function Style
 
         */
 
         let fn_style = self.parse_unsafety();
-        let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many};
 
-        let lifetime_defs = if self.eat(&token::Lt) {
-            let lifetime_defs = self.parse_lifetime_defs();
-            self.expect_gt();
-
-            lifetime_defs
-        } else {
-            Vec::new()
-        };
+        let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
 
         let inputs = if self.eat(&token::OrOr) {
             Vec::new()
@@ -1152,7 +1203,7 @@ impl<'a> Parser<'a> {
 
         TyClosure(P(ClosureTy {
             fn_style: fn_style,
-            onceness: onceness,
+            onceness: Many,
             bounds: bounds,
             decl: decl,
             lifetimes: lifetime_defs,
@@ -1167,36 +1218,23 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parse a function type (following the 'fn')
-    pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
-                            -> (P<FnDecl>, Vec<ast::LifetimeDef>) {
-        /*
-
-        (fn) <'lt> (S) -> T
-             ^~~~^ ^~^    ^
-               |    |     |
-               |    |   Return type
-               |  Argument types
-           Lifetime_defs
-
-        */
-        let lifetime_defs = if self.eat(&token::Lt) {
-            let lifetime_defs = self.parse_lifetime_defs();
-            self.expect_gt();
-            lifetime_defs
+    /// Parses `[ 'for' '<' lifetime_defs '>' ]'
+    fn parse_legacy_lifetime_defs(&mut self,
+                                  lifetime_defs: Vec<ast::LifetimeDef>)
+                                  -> Vec<ast::LifetimeDef>
+    {
+        if self.eat(&token::Lt) {
+            if lifetime_defs.is_empty() {
+                self.warn("deprecated syntax, use `for` keyword now");
+                let lifetime_defs = self.parse_lifetime_defs();
+                self.expect_gt();
+                lifetime_defs
+            } else {
+                self.fatal("cannot use new `for` keyword and older syntax together");
+            }
         } else {
-            Vec::new()
-        };
-
-        let (inputs, variadic) = self.parse_fn_args(false, allow_variadic);
-        let (ret_style, ret_ty) = self.parse_ret_ty();
-        let decl = P(FnDecl {
-            inputs: inputs,
-            output: ret_ty,
-            cf: ret_style,
-            variadic: variadic
-        });
-        (decl, lifetime_defs)
+            lifetime_defs
+        }
     }
 
     /// Parses `type Foo;` in a trait declaration only. The `type` keyword has
@@ -1433,25 +1471,24 @@ impl<'a> Parser<'a> {
             self.expect(&token::CloseDelim(token::Bracket));
             t
         } else if self.token == token::BinOp(token::And) ||
-                self.token == token::AndAnd {
+                  self.token == token::AndAnd {
             // BORROWED POINTER
             self.expect_and();
             self.parse_borrowed_pointee()
-        } else if self.token.is_keyword(keywords::Extern) ||
-                  self.token.is_keyword(keywords::Unsafe) ||
-                self.token_is_bare_fn_keyword() {
-            // BARE FUNCTION
-            self.parse_ty_bare_fn()
-        } else if self.token_is_closure_keyword() ||
-                self.token == token::BinOp(token::Or) ||
-                self.token == token::OrOr ||
-                (self.token == token::Lt &&
-                 self.look_ahead(1, |t| {
-                     *t == token::Gt || t.is_lifetime()
-                 })) {
+        } else if self.token.is_keyword(keywords::For) {
+            self.parse_for_in_type()
+        } else if self.token_is_bare_fn_keyword() ||
+                  self.token_is_closure_keyword() {
+            // BARE FUNCTION OR CLOSURE
+            self.parse_ty_bare_fn_or_ty_closure(Vec::new())
+        } else if self.token == token::BinOp(token::Or) ||
+                  self.token == token::OrOr ||
+                  (self.token == token::Lt &&
+                   self.look_ahead(1, |t| {
+                       *t == token::Gt || t.is_lifetime()
+                   })) {
             // CLOSURE
-
-            self.parse_ty_closure()
+            self.parse_ty_closure(Vec::new())
         } else if self.eat_keyword(keywords::Typeof) {
             // TYPEOF
             // In order to not be ambiguous, the type must be surrounded by parens.
@@ -1460,7 +1497,7 @@ impl<'a> Parser<'a> {
             self.expect(&token::CloseDelim(token::Paren));
             TyTypeof(e)
         } else if self.eat_keyword(keywords::Proc) {
-            self.parse_proc_type()
+            self.parse_proc_type(Vec::new())
         } else if self.token == token::Lt {
             // QUALIFIED PATH
             self.bump();
@@ -1479,16 +1516,7 @@ impl<'a> Parser<'a> {
                   self.token.is_ident() ||
                   self.token.is_path() {
             // NAMED TYPE
-            let mode = if plus_allowed {
-                LifetimeAndTypesAndBounds
-            } else {
-                LifetimeAndTypesWithoutColons
-            };
-            let PathAndBounds {
-                path,
-                bounds
-            } = self.parse_path(mode);
-            TyPath(path, bounds, ast::DUMMY_NODE_ID)
+            self.parse_ty_path(plus_allowed)
         } else if self.eat(&token::Underscore) {
             // TYPE TO BE INFERRED
             TyInfer
@@ -3848,29 +3876,17 @@ impl<'a> Parser<'a> {
     }
 
     // matches bounds    = ( boundseq )?
-    // where   boundseq  = ( bound + boundseq ) | bound
-    // and     bound     = 'region | ty
+    // where   boundseq  = ( polybound + boundseq ) | polybound
+    // and     polybound = ( 'for' '<' 'region '>' )? bound
+    // and     bound     = 'region | trait_ref
     // NB: The None/Some distinction is important for issue #7264.
     fn parse_ty_param_bounds(&mut self)
                              -> OwnedSlice<TyParamBound>
     {
         let mut result = vec!();
         loop {
-            let lifetime_defs = if self.eat(&token::Lt) {
-                let lifetime_defs = self.parse_lifetime_defs();
-                self.expect_gt();
-                lifetime_defs
-            } else {
-                Vec::new()
-            };
             match self.token {
                 token::Lifetime(lifetime) => {
-                    if lifetime_defs.len() > 0 {
-                        let span = self.last_span;
-                        self.span_err(span, "lifetime declarations are not \
-                                             allowed here")
-                    }
-
                     result.push(RegionTyParamBound(ast::Lifetime {
                         id: ast::DUMMY_NODE_ID,
                         span: self.span,
@@ -3879,13 +3895,8 @@ impl<'a> Parser<'a> {
                     self.bump();
                 }
                 token::ModSep | token::Ident(..) => {
-                    let path =
-                        self.parse_path(LifetimeAndTypesWithoutColons).path;
-                    result.push(TraitTyParamBound(ast::TraitRef {
-                        path: path,
-                        ref_id: ast::DUMMY_NODE_ID,
-                        lifetimes: lifetime_defs,
-                    }))
+                    let poly_trait_ref = self.parse_poly_trait_ref();
+                    result.push(TraitTyParamBound(poly_trait_ref))
                 }
                 _ => break,
             }
@@ -3898,7 +3909,7 @@ impl<'a> Parser<'a> {
         return OwnedSlice::from_vec(result);
     }
 
-    fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
+    fn trait_ref_from_ident(ident: Ident, span: Span) -> TraitRef {
         let segment = ast::PathSegment {
             identifier: ident,
             parameters: ast::PathParameters::none()
@@ -3911,7 +3922,6 @@ impl<'a> Parser<'a> {
         ast::TraitRef {
             path: path,
             ref_id: ast::DUMMY_NODE_ID,
-            lifetimes: Vec::new(),
         }
     }
 
@@ -3927,7 +3937,7 @@ impl<'a> Parser<'a> {
         let mut unbound = None;
         if self.eat(&token::Question) {
             let tref = Parser::trait_ref_from_ident(ident, span);
-            unbound = Some(TraitTyParamBound(tref));
+            unbound = Some(tref);
             span = self.span;
             ident = self.parse_ident();
         }
@@ -4538,7 +4548,6 @@ impl<'a> Parser<'a> {
                     Some(TraitRef {
                         path: (*path).clone(),
                         ref_id: node_id,
-                        lifetimes: Vec::new(),
                     })
                 }
                 TyPath(_, Some(_), _) => {
@@ -4568,6 +4577,35 @@ impl<'a> Parser<'a> {
          Some(attrs))
     }
 
+    /// Parse a::B<String,int>
+    fn parse_trait_ref(&mut self) -> TraitRef {
+        ast::TraitRef {
+            path: self.parse_path(LifetimeAndTypesWithoutColons).path,
+            ref_id: ast::DUMMY_NODE_ID,
+        }
+    }
+
+    fn parse_late_bound_lifetime_defs(&mut self) -> Vec<ast::LifetimeDef> {
+        if self.eat_keyword(keywords::For) {
+            self.expect(&token::Lt);
+            let lifetime_defs = self.parse_lifetime_defs();
+            self.expect_gt();
+            lifetime_defs
+        } else {
+            Vec::new()
+        }
+    }
+
+    /// Parse for<'l> a::B<String,int>
+    fn parse_poly_trait_ref(&mut self) -> PolyTraitRef {
+        let lifetime_defs = self.parse_late_bound_lifetime_defs();
+
+        ast::PolyTraitRef {
+            bound_lifetimes: lifetime_defs,
+            trait_ref: self.parse_trait_ref()
+        }
+    }
+
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self) -> ItemInfo {
         let class_name = self.parse_ident();
@@ -4681,7 +4719,7 @@ impl<'a> Parser<'a> {
         else { Inherited }
     }
 
-    fn parse_for_sized(&mut self) -> Option<ast::TyParamBound> {
+    fn parse_for_sized(&mut self) -> Option<ast::TraitRef> {
         if self.eat_keyword(keywords::For) {
             let span = self.span;
             let ident = self.parse_ident();
@@ -4691,7 +4729,7 @@ impl<'a> Parser<'a> {
                 return None;
             }
             let tref = Parser::trait_ref_from_ident(ident, span);
-            Some(TraitTyParamBound(tref))
+            Some(tref)
         } else {
             None
         }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 63e2c5499e8..5b57a875c4a 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -743,6 +743,9 @@ impl<'a> State<'a> {
             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::TyQPath(ref qpath) => {
                 try!(word(&mut self.s, "<"));
                 try!(self.print_type(&*qpath.for_type));
@@ -960,7 +963,7 @@ impl<'a> State<'a> {
                 try!(self.print_ident(item.ident));
                 try!(self.print_generics(generics));
                 match unbound {
-                    &Some(TraitTyParamBound(ref tref)) => {
+                    &Some(ref tref) => {
                         try!(space(&mut self.s));
                         try!(self.word_space("for"));
                         try!(self.print_trait_ref(tref));
@@ -995,19 +998,21 @@ impl<'a> State<'a> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
-        if t.lifetimes.len() > 0 {
-            try!(self.print_generics(&ast::Generics {
-                lifetimes: t.lifetimes.clone(),
-                ty_params: OwnedSlice::empty(),
-                where_clause: ast::WhereClause {
-                    id: ast::DUMMY_NODE_ID,
-                    predicates: Vec::new(),
-                },
-            }));
-        }
         self.print_path(&t.path, false)
     }
 
+    fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> IoResult<()> {
+        if !t.bound_lifetimes.is_empty() {
+            try!(word(&mut self.s, "for<"));
+            for lifetime_def in t.bound_lifetimes.iter() {
+                try!(self.print_lifetime_def(lifetime_def));
+            }
+            try!(word(&mut self.s, ">"));
+        }
+
+        self.print_trait_ref(&t.trait_ref)
+    }
+
     pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
                           generics: &ast::Generics, ident: ast::Ident,
                           span: codemap::Span,
@@ -2383,7 +2388,7 @@ impl<'a> State<'a> {
 
                 try!(match *bound {
                     TraitTyParamBound(ref tref) => {
-                        self.print_trait_ref(tref)
+                        self.print_poly_trait_ref(tref)
                     }
                     RegionTyParamBound(ref lt) => {
                         self.print_lifetime(lt)
@@ -2450,7 +2455,7 @@ impl<'a> State<'a> {
 
     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
         match param.unbound {
-            Some(TraitTyParamBound(ref tref)) => {
+            Some(ref tref) => {
                 try!(self.print_trait_ref(tref));
                 try!(self.word_space("?"));
             }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 9751abacbd3..1b1d1e9cace 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -75,6 +75,10 @@ pub trait Visitor<'v> {
     }
     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_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
+        walk_poly_trait_ref(self, t)
+    }
     fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
         walk_struct_def(self, s)
     }
@@ -202,9 +206,20 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
 
 /// Like with walk_method_helper this doesn't correspond to a method
 /// in Visitor, and so it gets a _helper suffix.
-pub fn walk_trait_ref_helper<'v,V>(visitor: &mut V, trait_ref: &'v TraitRef)
-                                   where V: Visitor<'v> {
-    walk_lifetime_decls(visitor, &trait_ref.lifetimes);
+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);
+    visitor.visit_trait_ref(&trait_ref.trait_ref);
+}
+
+/// Like with walk_method_helper this doesn't correspond to a method
+/// in Visitor, and so it gets a _helper suffix.
+pub fn walk_trait_ref<'v,V>(visitor: &mut V,
+                                   trait_ref: &'v TraitRef)
+    where V: Visitor<'v>
+{
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
@@ -248,8 +263,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                  ref impl_items) => {
             visitor.visit_generics(type_parameters);
             match *trait_reference {
-                Some(ref trait_reference) => walk_trait_ref_helper(visitor,
-                                                                   trait_reference),
+                Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
                 None => ()
             }
             visitor.visit_ty(&**typ);
@@ -383,6 +397,9 @@ 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)
+        }
         TyTypeof(ref expression) => {
             visitor.visit_expr(&**expression)
         }
@@ -497,7 +514,7 @@ pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
     for bound in bounds.iter() {
         match *bound {
             TraitTyParamBound(ref typ) => {
-                walk_trait_ref_helper(visitor, typ)
+                visitor.visit_poly_trait_ref(typ)
             }
             RegionTyParamBound(ref lifetime) => {
                 visitor.visit_lifetime_ref(lifetime);