about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-08-27 21:46:52 -0400
committerNiko Matsakis <niko@alum.mit.edu>2014-08-27 21:46:52 -0400
commit1b487a890695e7d6dfbfe5dcd7d4fa0e8ca8003f (patch)
tree552fabade603ab0d148a49ae3cf1abd3f399740a /src/libsyntax
parent3ee047ae1ffab454270bc1859b3beef3556ef8f9 (diff)
downloadrust-1b487a890695e7d6dfbfe5dcd7d4fa0e8ca8003f.tar.gz
rust-1b487a890695e7d6dfbfe5dcd7d4fa0e8ca8003f.zip
Implement generalized object and type parameter bounds (Fixes #16462)
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs19
-rw-r--r--src/libsyntax/ast_map/mod.rs22
-rw-r--r--src/libsyntax/ast_util.rs8
-rw-r--r--src/libsyntax/diagnostics/plugin.rs18
-rw-r--r--src/libsyntax/ext/asm.rs4
-rw-r--r--src/libsyntax/ext/base.rs70
-rw-r--r--src/libsyntax/ext/bytes.rs6
-rw-r--r--src/libsyntax/ext/cfg.rs6
-rw-r--r--src/libsyntax/ext/concat.rs2
-rw-r--r--src/libsyntax/ext/concat_idents.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs6
-rw-r--r--src/libsyntax/ext/env.rs8
-rw-r--r--src/libsyntax/ext/expand.rs191
-rw-r--r--src/libsyntax/ext/fmt.rs2
-rw-r--r--src/libsyntax/ext/format.rs11
-rw-r--r--src/libsyntax/ext/log_syntax.rs8
-rw-r--r--src/libsyntax/ext/quote.rs39
-rw-r--r--src/libsyntax/ext/source_util.rs16
-rw-r--r--src/libsyntax/ext/trace_macros.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs39
-rw-r--r--src/libsyntax/fold.rs42
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/parse/parser.rs184
-rw-r--r--src/libsyntax/print/pp.rs4
-rw-r--r--src/libsyntax/print/pprust.rs139
-rw-r--r--src/libsyntax/visit.rs38
26 files changed, 426 insertions, 463 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 7d5787092a5..d574a02fded 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -224,16 +224,17 @@ pub static DUMMY_NODE_ID: NodeId = -1;
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum TyParamBound {
     TraitTyParamBound(TraitRef),
-    StaticRegionTyParamBound,
     UnboxedFnTyParamBound(UnboxedFnTy),
-    OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands
+    RegionTyParamBound(Lifetime)
 }
 
+pub type TyParamBounds = OwnedSlice<TyParamBound>;
+
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
-    pub bounds: OwnedSlice<TyParamBound>,
+    pub bounds: TyParamBounds,
     pub unbound: Option<TyParamBound>,
     pub default: Option<P<Ty>>,
     pub span: Span
@@ -892,11 +893,7 @@ pub struct ClosureTy {
     pub fn_style: FnStyle,
     pub onceness: Onceness,
     pub decl: P<FnDecl>,
-    /// Optional optvec distinguishes between "fn()" and "fn:()" so we can
-    /// implement issue #7264. None means "fn()", which means infer a default
-    /// bound based on pointer sigil during typeck. Some(Empty) means "fn:()",
-    /// which means use no bounds (e.g., not even Owned on a ~fn()).
-    pub bounds: Option<OwnedSlice<TyParamBound>>,
+    pub bounds: TyParamBounds,
 }
 
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
@@ -923,12 +920,12 @@ pub enum Ty_ {
     TyFixedLengthVec(P<Ty>, Gc<Expr>),
     TyPtr(MutTy),
     TyRptr(Option<Lifetime>, MutTy),
-    TyClosure(Gc<ClosureTy>, Option<Lifetime>),
+    TyClosure(Gc<ClosureTy>),
     TyProc(Gc<ClosureTy>),
     TyBareFn(Gc<BareFnTy>),
     TyUnboxedFn(Gc<UnboxedFnTy>),
     TyTup(Vec<P<Ty>> ),
-    TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
+    TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above
     /// No-op; kept solely so that we can pretty-print faithfully
     TyParen(P<Ty>),
     TyTypeof(Gc<Expr>),
@@ -1281,7 +1278,7 @@ pub enum Item_ {
     ItemTrait(Generics,
               Option<TyParamBound>, // (optional) default bound not required for Self.
                                     // Currently, only Sized makes sense here.
-              Vec<TraitRef> ,
+              TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Generics,
              Option<TraitRef>, // (optional) trait this impl implements
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 5fccf6cc3f0..993c5ce676a 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -68,10 +68,15 @@ impl<'a> Iterator<PathElem> for LinkedPath<'a> {
     }
 }
 
-// HACK(eddyb) move this into libstd (value wrapper for slice::Items).
+#[cfg(stage0)]
 #[deriving(Clone)]
 pub struct Values<'a, T>(pub slice::Items<'a, T>);
 
+// HACK(eddyb) move this into libstd (value wrapper for slice::Items).
+#[cfg(not(stage0))]
+#[deriving(Clone)]
+pub struct Values<'a, T:'a>(pub slice::Items<'a, T>);
+
 impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
     fn next(&mut self) -> Option<T> {
         let &Values(ref mut items) = self;
@@ -478,6 +483,7 @@ impl Map {
     }
 }
 
+#[cfg(stage0)]
 pub struct NodesMatchingSuffix<'a, S> {
     map: &'a Map,
     item_name: &'a S,
@@ -485,6 +491,14 @@ pub struct NodesMatchingSuffix<'a, S> {
     idx: NodeId,
 }
 
+#[cfg(not(stage0))]
+pub struct NodesMatchingSuffix<'a, S:'a> {
+    map: &'a Map,
+    item_name: &'a S,
+    in_which: &'a [S],
+    idx: NodeId,
+}
+
 impl<'a,S:Str> NodesMatchingSuffix<'a,S> {
     /// Returns true only if some suffix of the module path for parent
     /// matches `self.in_which`.
@@ -676,11 +690,7 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
                     None => {}
                 }
             }
-            ItemTrait(_, _, ref traits, ref methods) => {
-                for t in traits.iter() {
-                    self.insert(t.ref_id, EntryItem(self.parent, i));
-                }
-
+            ItemTrait(_, _, _, ref methods) => {
                 for tm in methods.iter() {
                     match *tm {
                         RequiredMethod(ref m) => {
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 1a4b41404be..cc586a3affa 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -349,12 +349,20 @@ pub trait IdVisitingOperation {
 /// A visitor that applies its operation to all of the node IDs
 /// in a visitable thing.
 
+#[cfg(stage0)]
 pub struct IdVisitor<'a, O> {
     pub operation: &'a O,
     pub pass_through_items: bool,
     pub visited_outermost: bool,
 }
 
+#[cfg(not(stage0))]
+pub struct IdVisitor<'a, O:'a> {
+    pub operation: &'a O,
+    pub pass_through_items: bool,
+    pub visited_outermost: bool,
+}
+
 impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
     fn visit_generics_helper(&self, generics: &Generics) {
         for type_parameter in generics.ty_params.iter() {
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 209296989fa..25a6a4c01bd 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -45,8 +45,10 @@ fn with_used_diagnostics<T>(f: |&mut HashMap<Name, Span>| -> T) -> T {
     }
 }
 
-pub fn expand_diagnostic_used(ecx: &mut ExtCtxt, span: Span,
-                              token_tree: &[TokenTree]) -> Box<MacResult> {
+pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
+                                   span: Span,
+                                   token_tree: &[TokenTree])
+                                   -> Box<MacResult+'cx> {
     let code = match token_tree {
         [ast::TTTok(_, token::IDENT(code, _))] => code,
         _ => unreachable!()
@@ -75,8 +77,10 @@ pub fn expand_diagnostic_used(ecx: &mut ExtCtxt, span: Span,
     MacExpr::new(quote_expr!(ecx, ()))
 }
 
-pub fn expand_register_diagnostic(ecx: &mut ExtCtxt, span: Span,
-                                  token_tree: &[TokenTree]) -> Box<MacResult> {
+pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
+                                       span: Span,
+                                       token_tree: &[TokenTree])
+                                       -> Box<MacResult+'cx> {
     let (code, description) = match token_tree {
         [ast::TTTok(_, token::IDENT(ref code, _))] => {
             (code, None)
@@ -101,8 +105,10 @@ pub fn expand_register_diagnostic(ecx: &mut ExtCtxt, span: Span,
     MacItem::new(quote_item!(ecx, mod $sym {}).unwrap())
 }
 
-pub fn expand_build_diagnostic_array(ecx: &mut ExtCtxt, span: Span,
-                                     token_tree: &[TokenTree]) -> Box<MacResult> {
+pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
+                                          span: Span,
+                                          token_tree: &[TokenTree])
+                                          -> Box<MacResult+'cx> {
     let name = match token_tree {
         [ast::TTTok(_, token::IDENT(ref name, _))] => name,
         _ => unreachable!()
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 180f2409b8a..8028d51a7b5 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -45,8 +45,8 @@ impl State {
 
 static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
 
-pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                  -> Box<base::MacResult> {
+pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                       -> Box<base::MacResult+'cx> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut asm = InternedString::new("");
     let mut asm_str_style = None;
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 01d3920a254..b3b66a6a604 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -52,23 +52,23 @@ pub struct BasicMacroExpander {
 
 /// Represents a thing that maps token trees to Macro Results
 pub trait TTMacroExpander {
-    fn expand(&self,
-              ecx: &mut ExtCtxt,
-              span: Span,
-              token_tree: &[ast::TokenTree])
-              -> Box<MacResult>;
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt,
+                   span: Span,
+                   token_tree: &[ast::TokenTree])
+                   -> Box<MacResult+'cx>;
 }
 
 pub type MacroExpanderFn =
-    fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
-       -> Box<MacResult>;
+    fn<'cx>(ecx: &'cx mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
+            -> Box<MacResult+'cx>;
 
 impl TTMacroExpander for BasicMacroExpander {
-    fn expand(&self,
-              ecx: &mut ExtCtxt,
-              span: Span,
-              token_tree: &[ast::TokenTree])
-              -> Box<MacResult> {
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt,
+                   span: Span,
+                   token_tree: &[ast::TokenTree])
+                   -> Box<MacResult+'cx> {
         (self.expander)(ecx, span, token_tree)
     }
 }
@@ -79,27 +79,27 @@ pub struct BasicIdentMacroExpander {
 }
 
 pub trait IdentMacroExpander {
-    fn expand(&self,
-              cx: &mut ExtCtxt,
-              sp: Span,
-              ident: ast::Ident,
-              token_tree: Vec<ast::TokenTree> )
-              -> Box<MacResult>;
+    fn expand<'cx>(&self,
+                   cx: &'cx mut ExtCtxt,
+                   sp: Span,
+                   ident: ast::Ident,
+                   token_tree: Vec<ast::TokenTree> )
+                   -> Box<MacResult+'cx>;
 }
 
 impl IdentMacroExpander for BasicIdentMacroExpander {
-    fn expand(&self,
-              cx: &mut ExtCtxt,
-              sp: Span,
-              ident: ast::Ident,
-              token_tree: Vec<ast::TokenTree> )
-              -> Box<MacResult> {
+    fn expand<'cx>(&self,
+                   cx: &'cx mut ExtCtxt,
+                   sp: Span,
+                   ident: ast::Ident,
+                   token_tree: Vec<ast::TokenTree> )
+                   -> Box<MacResult+'cx> {
         (self.expander)(cx, sp, ident, token_tree)
     }
 }
 
 pub type IdentMacroExpanderFn =
-    fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
+    fn<'cx>(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
 
 /// The result of a macro expansion. The return values of the various
 /// methods are spliced into the AST at the callsite of the macro (or
@@ -146,8 +146,8 @@ pub struct MacExpr {
     e: Gc<ast::Expr>,
 }
 impl MacExpr {
-    pub fn new(e: Gc<ast::Expr>) -> Box<MacResult> {
-        box MacExpr { e: e } as Box<MacResult>
+    pub fn new(e: Gc<ast::Expr>) -> Box<MacResult+'static> {
+        box MacExpr { e: e } as Box<MacResult+'static>
     }
 }
 impl MacResult for MacExpr {
@@ -160,8 +160,8 @@ pub struct MacPat {
     p: Gc<ast::Pat>,
 }
 impl MacPat {
-    pub fn new(p: Gc<ast::Pat>) -> Box<MacResult> {
-        box MacPat { p: p } as Box<MacResult>
+    pub fn new(p: Gc<ast::Pat>) -> Box<MacResult+'static> {
+        box MacPat { p: p } as Box<MacResult+'static>
     }
 }
 impl MacResult for MacPat {
@@ -174,8 +174,8 @@ pub struct MacItem {
     i: Gc<ast::Item>
 }
 impl MacItem {
-    pub fn new(i: Gc<ast::Item>) -> Box<MacResult> {
-        box MacItem { i: i } as Box<MacResult>
+    pub fn new(i: Gc<ast::Item>) -> Box<MacResult+'static> {
+        box MacItem { i: i } as Box<MacResult+'static>
     }
 }
 impl MacResult for MacItem {
@@ -203,8 +203,8 @@ impl DummyResult {
     ///
     /// Use this as a return value after hitting any errors and
     /// calling `span_err`.
-    pub fn any(sp: Span) -> Box<MacResult> {
-        box DummyResult { expr_only: false, span: sp } as Box<MacResult>
+    pub fn any(sp: Span) -> Box<MacResult+'static> {
+        box DummyResult { expr_only: false, span: sp } as Box<MacResult+'static>
     }
 
     /// Create a default MacResult that can only be an expression.
@@ -212,8 +212,8 @@ impl DummyResult {
     /// Use this for macros that must expand to an expression, so even
     /// if an error is encountered internally, the user will receive
     /// an error that they also used it in the wrong place.
-    pub fn expr(sp: Span) -> Box<MacResult> {
-        box DummyResult { expr_only: true, span: sp } as Box<MacResult>
+    pub fn expr(sp: Span) -> Box<MacResult+'static> {
+        box DummyResult { expr_only: true, span: sp } as Box<MacResult+'static>
     }
 
     /// A plain dummy expression.
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index 6ea55096348..18367511495 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -17,8 +17,10 @@ use ext::base;
 use ext::build::AstBuilder;
 
 
-pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
+                              sp: Span,
+                              tts: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
     cx.span_warn(sp, "`bytes!` is deprecated, use `b\"foo\"` literals instead");
     cx.parse_sess.span_diagnostic.span_note(sp,
         "see http://doc.rust-lang.org/rust.html#byte-and-byte-string-literals \
diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs
index c2930662bc4..0c3a951c982 100644
--- a/src/libsyntax/ext/cfg.rs
+++ b/src/libsyntax/ext/cfg.rs
@@ -26,8 +26,10 @@ use parse::token::InternedString;
 use parse::token;
 
 
-pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                  -> Box<base::MacResult> {
+pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
+                       sp: Span,
+                       tts: &[ast::TokenTree])
+                       -> Box<base::MacResult+'static> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut cfgs = Vec::new();
     // parse `cfg!(meta_item, meta_item(x,y), meta_item="foo", ...)`
diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs
index dd1153bf666..ea7a4d061c0 100644
--- a/src/libsyntax/ext/concat.rs
+++ b/src/libsyntax/ext/concat.rs
@@ -19,7 +19,7 @@ use std::string::String;
 pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                          sp: codemap::Span,
                          tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+                         -> Box<base::MacResult+'static> {
     let es = match base::get_exprs_from_tts(cx, sp, tts) {
         Some(e) => e,
         None => return base::DummyResult::expr(sp)
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index 7cf901bbd5e..0ac26a3a904 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -18,8 +18,8 @@ use parse::token::{str_to_ident};
 
 use std::gc::GC;
 
-pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
     let mut res_str = String::new();
     for (i, e) in tts.iter().enumerate() {
         if i & 1 == 1 {
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 4b185419b40..50bdc296aad 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -407,9 +407,15 @@ impl<'a> TraitDef<'a> {
                     cx.typarambound(p.to_path(cx, self.span,
                                                   type_ident, generics))
                 }).collect();
+
             // require the current trait
             bounds.push(cx.typarambound(trait_path.clone()));
 
+            // also add in any bounds from the declaration
+            for declared_bound in ty_param.bounds.iter() {
+                bounds.push((*declared_bound).clone());
+            }
+
             cx.typaram(self.span,
                        ty_param.ident,
                        OwnedSlice::from_vec(bounds),
diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs
index b24cfb85794..aae92ae85fc 100644
--- a/src/libsyntax/ext/env.rs
+++ b/src/libsyntax/ext/env.rs
@@ -23,8 +23,8 @@ use parse::token;
 
 use std::os;
 
-pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
     let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
         None => return DummyResult::expr(sp),
         Some(v) => v
@@ -59,8 +59,8 @@ pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     MacExpr::new(e)
 }
 
-pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                  -> Box<base::MacResult> {
+pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                       -> Box<base::MacResult+'cx> {
     let exprs = match get_exprs_from_tts(cx, sp, tts) {
         Some(ref exprs) if exprs.len() == 0 => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d918b28d4dc..9dbea1c9ac2 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -31,6 +31,10 @@ use util::small_vector::SmallVector;
 
 use std::gc::{Gc, GC};
 
+enum Either<L,R> {
+    Left(L),
+    Right(R)
+}
 
 fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
     match e.node {
@@ -102,7 +106,8 @@ fn expand_mac_invoc<T>(mac: &ast::Mac, span: &codemap::Span,
                        parse_thunk: |Box<MacResult>|->Option<T>,
                        mark_thunk: |T,Mrk|->T,
                        fld: &mut MacroExpander)
-    -> Option<T> {
+                       -> Option<T>
+{
     match (*mac).node {
         // it would almost certainly be cleaner to pass the whole
         // macro invocation in, rather than pulling it apart and
@@ -149,10 +154,13 @@ fn expand_mac_invoc<T>(mac: &ast::Mac, span: &codemap::Span,
                         // the macro.
                         let mac_span = original_span(fld.cx);
 
-                        let expanded = expandfun.expand(fld.cx,
-                                                        mac_span.call_site,
-                                                        marked_before.as_slice());
-                        let parsed = match parse_thunk(expanded) {
+                        let opt_parsed = {
+                            let expanded = expandfun.expand(fld.cx,
+                                                            mac_span.call_site,
+                                                            marked_before.as_slice());
+                            parse_thunk(expanded)
+                        };
+                        let parsed = match opt_parsed {
                             Some(e) => e,
                             None => {
                                 fld.cx.span_err(
@@ -358,7 +366,8 @@ fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
 fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
-                       -> SmallVector<Gc<ast::Item>> {
+                   -> SmallVector<Gc<ast::Item>>
+{
     let (pth, tts) = match it.node {
         ItemMac(codemap::Spanned {
             node: MacInvocTT(ref pth, ref tts, _),
@@ -372,86 +381,93 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
     let extname = pth.segments.get(0).identifier;
     let extnamestr = token::get_ident(extname);
     let fm = fresh_mark();
-    let expanded = match fld.cx.syntax_env.find(&extname.name) {
-        None => {
-            fld.cx.span_err(pth.span,
-                            format!("macro undefined: '{}!'",
-                                    extnamestr).as_slice());
-            // let compilation continue
-            return SmallVector::zero();
-        }
+    let def_or_items = {
+        let expanded = match fld.cx.syntax_env.find(&extname.name) {
+            None => {
+                fld.cx.span_err(pth.span,
+                                format!("macro undefined: '{}!'",
+                                        extnamestr).as_slice());
+                // let compilation continue
+                return SmallVector::zero();
+            }
 
-        Some(rc) => match *rc {
-            NormalTT(ref expander, span) => {
-                if it.ident.name != parse::token::special_idents::invalid.name {
-                    fld.cx
-                    .span_err(pth.span,
-                                format!("macro {}! expects no ident argument, \
+            Some(rc) => match *rc {
+                NormalTT(ref expander, span) => {
+                    if it.ident.name != parse::token::special_idents::invalid.name {
+                        fld.cx
+                            .span_err(pth.span,
+                                      format!("macro {}! expects no ident argument, \
                                         given '{}'",
-                                        extnamestr,
-                                        token::get_ident(it.ident)).as_slice());
-                    return SmallVector::zero();
+                                      extnamestr,
+                                      token::get_ident(it.ident)).as_slice());
+                        return SmallVector::zero();
+                    }
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: it.span,
+                        callee: NameAndSpan {
+                            name: extnamestr.get().to_string(),
+                            format: MacroBang,
+                            span: span
+                        }
+                    });
+                    // mark before expansion:
+                    let marked_before = mark_tts(tts.as_slice(), fm);
+                    expander.expand(fld.cx, it.span, marked_before.as_slice())
                 }
-                fld.cx.bt_push(ExpnInfo {
-                    call_site: it.span,
-                    callee: NameAndSpan {
-                        name: extnamestr.get().to_string(),
-                        format: MacroBang,
-                        span: span
+                IdentTT(ref expander, span) => {
+                    if it.ident.name == parse::token::special_idents::invalid.name {
+                        fld.cx.span_err(pth.span,
+                                        format!("macro {}! expects an ident argument",
+                                                extnamestr.get()).as_slice());
+                        return SmallVector::zero();
                     }
-                });
-                // mark before expansion:
-                let marked_before = mark_tts(tts.as_slice(), fm);
-                expander.expand(fld.cx, it.span, marked_before.as_slice())
-            }
-            IdentTT(ref expander, span) => {
-                if it.ident.name == parse::token::special_idents::invalid.name {
-                    fld.cx.span_err(pth.span,
-                                    format!("macro {}! expects an ident argument",
-                                            extnamestr.get()).as_slice());
-                    return SmallVector::zero();
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: it.span,
+                        callee: NameAndSpan {
+                            name: extnamestr.get().to_string(),
+                            format: MacroBang,
+                            span: span
+                        }
+                    });
+                    // mark before expansion:
+                    let marked_tts = mark_tts(tts.as_slice(), fm);
+                    expander.expand(fld.cx, it.span, it.ident, marked_tts)
                 }
-                fld.cx.bt_push(ExpnInfo {
-                    call_site: it.span,
-                    callee: NameAndSpan {
-                        name: extnamestr.get().to_string(),
-                        format: MacroBang,
-                        span: span
+                LetSyntaxTT(ref expander, span) => {
+                    if it.ident.name == parse::token::special_idents::invalid.name {
+                        fld.cx.span_err(pth.span,
+                                        format!("macro {}! expects an ident argument",
+                                                extnamestr.get()).as_slice());
+                        return SmallVector::zero();
                     }
-                });
-                // mark before expansion:
-                let marked_tts = mark_tts(tts.as_slice(), fm);
-                expander.expand(fld.cx, it.span, it.ident, marked_tts)
-            }
-            LetSyntaxTT(ref expander, span) => {
-                if it.ident.name == parse::token::special_idents::invalid.name {
-                    fld.cx.span_err(pth.span,
-                                    format!("macro {}! expects an ident argument",
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: it.span,
+                        callee: NameAndSpan {
+                            name: extnamestr.get().to_string(),
+                            format: MacroBang,
+                            span: span
+                        }
+                    });
+                    // DON'T mark before expansion:
+                    expander.expand(fld.cx, it.span, it.ident, tts)
+                }
+                _ => {
+                    fld.cx.span_err(it.span,
+                                    format!("{}! is not legal in item position",
                                             extnamestr.get()).as_slice());
                     return SmallVector::zero();
                 }
-                fld.cx.bt_push(ExpnInfo {
-                    call_site: it.span,
-                    callee: NameAndSpan {
-                        name: extnamestr.get().to_string(),
-                        format: MacroBang,
-                        span: span
-                    }
-                });
-                // DON'T mark before expansion:
-                expander.expand(fld.cx, it.span, it.ident, tts)
-            }
-            _ => {
-                fld.cx.span_err(it.span,
-                                format!("{}! is not legal in item position",
-                                        extnamestr.get()).as_slice());
-                return SmallVector::zero();
             }
+        };
+
+        match expanded.make_def() {
+            Some(def) => Left(def),
+            None => Right(expanded.make_items())
         }
     };
 
-    let items = match expanded.make_def() {
-        Some(MacroDef { name, ext }) => {
+    let items = match def_or_items {
+        Left(MacroDef { name, ext }) => {
             // hidden invariant: this should only be possible as the
             // result of expanding a LetSyntaxTT, and thus doesn't
             // need to be marked. Not that it could be marked anyway.
@@ -462,23 +478,20 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
             }
             SmallVector::zero()
         }
-        None => {
-            match expanded.make_items() {
-                Some(items) => {
-                    items.move_iter()
-                        .map(|i| mark_item(i, fm))
-                        .flat_map(|i| fld.fold_item(i).move_iter())
-                        .collect()
-                }
-                None => {
-                    fld.cx.span_err(pth.span,
-                                    format!("non-item macro in item position: {}",
-                                            extnamestr.get()).as_slice());
-                    return SmallVector::zero();
-                }
-            }
+        Right(Some(items)) => {
+            items.move_iter()
+                .map(|i| mark_item(i, fm))
+                .flat_map(|i| fld.fold_item(i).move_iter())
+                .collect()
+        }
+        Right(None) => {
+            fld.cx.span_err(pth.span,
+                            format!("non-item macro in item position: {}",
+                                    extnamestr.get()).as_slice());
+            return SmallVector::zero();
         }
     };
+
     fld.cx.bt_pop();
     return items;
 }
@@ -901,7 +914,7 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: &ast::FnDecl, block: Gc<ast::Blo
 }
 
 /// A tree-folder that performs macro expansion
-pub struct MacroExpander<'a, 'b> {
+pub struct MacroExpander<'a, 'b:'a> {
     pub cx: &'a mut ExtCtxt<'b>,
 }
 
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index 4185458bfbe..5352cfaf749 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -19,7 +19,7 @@ use ext::build::AstBuilder;
 pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt,
                          sp: Span,
                          _tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+                         -> Box<base::MacResult+'static> {
     ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead");
     ecx.parse_sess.span_diagnostic.span_note(sp,
         "see http://doc.rust-lang.org/std/fmt/ \
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 124e9e95942..0994abaadc7 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -33,7 +33,7 @@ enum Position {
     Named(String),
 }
 
-struct Context<'a, 'b> {
+struct Context<'a, 'b:'a> {
     ecx: &'a mut ExtCtxt<'b>,
     fmtsp: Span,
 
@@ -668,8 +668,9 @@ impl<'a, 'b> Context<'a, 'b> {
     }
 }
 
-pub fn expand_format_args(ecx: &mut ExtCtxt, sp: Span,
-                          tts: &[ast::TokenTree]) -> Box<base::MacResult> {
+pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp: Span,
+                               tts: &[ast::TokenTree])
+                               -> Box<base::MacResult+'cx> {
 
     match parse_args(ecx, sp, false, tts) {
         (invocation, Some((efmt, args, order, names))) => {
@@ -680,8 +681,8 @@ pub fn expand_format_args(ecx: &mut ExtCtxt, sp: Span,
     }
 }
 
-pub fn expand_format_args_method(ecx: &mut ExtCtxt, sp: Span,
-                                 tts: &[ast::TokenTree]) -> Box<base::MacResult> {
+pub fn expand_format_args_method<'cx>(ecx: &'cx mut ExtCtxt, sp: Span,
+                                      tts: &[ast::TokenTree]) -> Box<base::MacResult+'cx> {
 
     match parse_args(ecx, sp, true, tts) {
         (invocation, Some((efmt, args, order, names))) => {
diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs
index 1f4d087abd0..8df5746e412 100644
--- a/src/libsyntax/ext/log_syntax.rs
+++ b/src/libsyntax/ext/log_syntax.rs
@@ -15,10 +15,10 @@ use print;
 
 use std::rc::Rc;
 
-pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
-                         sp: codemap::Span,
-                         tt: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
+                              sp: codemap::Span,
+                              tt: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
 
     cx.print_backtrace();
     println!("{}", print::pprust::tt_to_string(&ast::TTDelim(
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index d7d6c20b475..0c41db7ecd6 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -410,35 +410,36 @@ pub mod rt {
 
 }
 
-pub fn expand_quote_tokens(cx: &mut ExtCtxt,
-                           sp: Span,
-                           tts: &[ast::TokenTree])
-                           -> Box<base::MacResult> {
+pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt,
+                                sp: Span,
+                                tts: &[ast::TokenTree])
+                                -> Box<base::MacResult+'cx> {
     let (cx_expr, expr) = expand_tts(cx, sp, tts);
     let expanded = expand_wrapper(cx, sp, cx_expr, expr);
     base::MacExpr::new(expanded)
 }
 
-pub fn expand_quote_expr(cx: &mut ExtCtxt,
-                         sp: Span,
-                         tts: &[ast::TokenTree]) -> Box<base::MacResult> {
+pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt,
+                              sp: Span,
+                              tts: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
     let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
     base::MacExpr::new(expanded)
 }
 
-pub fn expand_quote_item(cx: &mut ExtCtxt,
-                         sp: Span,
-                         tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt,
+                              sp: Span,
+                              tts: &[ast::TokenTree])
+                              -> Box<base::MacResult+'cx> {
     let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes",
                                     vec!(), tts);
     base::MacExpr::new(expanded)
 }
 
-pub fn expand_quote_pat(cx: &mut ExtCtxt,
-                        sp: Span,
-                        tts: &[ast::TokenTree])
-                        -> Box<base::MacResult> {
+pub fn expand_quote_pat<'cx>(cx: &'cx mut ExtCtxt,
+                             sp: Span,
+                             tts: &[ast::TokenTree])
+                             -> Box<base::MacResult+'cx> {
     let expanded = expand_parse_call(cx, sp, "parse_pat", vec!(), tts);
     base::MacExpr::new(expanded)
 }
@@ -446,7 +447,7 @@ pub fn expand_quote_pat(cx: &mut ExtCtxt,
 pub fn expand_quote_arm(cx: &mut ExtCtxt,
                         sp: Span,
                         tts: &[ast::TokenTree])
-                        -> Box<base::MacResult> {
+                        -> Box<base::MacResult+'static> {
     let expanded = expand_parse_call(cx, sp, "parse_arm", vec!(), tts);
     base::MacExpr::new(expanded)
 }
@@ -454,7 +455,7 @@ pub fn expand_quote_arm(cx: &mut ExtCtxt,
 pub fn expand_quote_ty(cx: &mut ExtCtxt,
                        sp: Span,
                        tts: &[ast::TokenTree])
-                       -> Box<base::MacResult> {
+                       -> Box<base::MacResult+'static> {
     let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
     let expanded = expand_parse_call(cx, sp, "parse_ty",
                                      vec!(e_param_colons), tts);
@@ -464,7 +465,7 @@ pub fn expand_quote_ty(cx: &mut ExtCtxt,
 pub fn expand_quote_method(cx: &mut ExtCtxt,
                            sp: Span,
                            tts: &[ast::TokenTree])
-                           -> Box<base::MacResult> {
+                           -> Box<base::MacResult+'static> {
     let e_param_colons = cx.expr_none(sp);
     let expanded = expand_parse_call(cx, sp, "parse_method",
                                      vec!(e_param_colons), tts);
@@ -474,7 +475,7 @@ pub fn expand_quote_method(cx: &mut ExtCtxt,
 pub fn expand_quote_stmt(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[ast::TokenTree])
-                         -> Box<base::MacResult> {
+                         -> Box<base::MacResult+'static> {
     let e_attrs = cx.expr_vec_ng(sp);
     let expanded = expand_parse_call(cx, sp, "parse_stmt",
                                     vec!(e_attrs), tts);
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 703adcbd335..5cc0ec4a122 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -29,7 +29,7 @@ use std::rc::Rc;
 
 /// line!(): expands to the current line number
 pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                   -> Box<base::MacResult> {
+                   -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "line!");
 
     let topmost = topmost_expn_info(cx.backtrace().unwrap());
@@ -40,7 +40,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
 /* col!(): expands to the current column number */
 pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                  -> Box<base::MacResult> {
+                  -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "col!");
 
     let topmost = topmost_expn_info(cx.backtrace().unwrap());
@@ -52,7 +52,7 @@ pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 /// The filemap (`loc.file`) contains a bunch more information we could spit
 /// out if we wanted.
 pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                   -> Box<base::MacResult> {
+                   -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "file!");
 
     let topmost = topmost_expn_info(cx.backtrace().unwrap());
@@ -62,14 +62,14 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 }
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                        -> Box<base::MacResult> {
+                        -> Box<base::MacResult+'static> {
     let s = pprust::tts_to_string(tts);
     base::MacExpr::new(cx.expr_str(sp,
                                    token::intern_and_get_ident(s.as_slice())))
 }
 
 pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                  -> Box<base::MacResult> {
+                  -> Box<base::MacResult+'static> {
     base::check_zero_tts(cx, sp, tts, "module_path!");
     let string = cx.mod_path()
                    .iter()
@@ -85,7 +85,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 /// This is generally a bad idea because it's going to behave
 /// unhygienically.
 pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                      -> Box<base::MacResult> {
+                      -> Box<base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
         Some(f) => f,
         None => return DummyResult::expr(sp),
@@ -105,7 +105,7 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
 // include_str! : read the given file, insert it as a literal string expr
 pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                          -> Box<base::MacResult> {
+                          -> Box<base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
         Some(f) => f,
         None => return DummyResult::expr(sp)
@@ -141,7 +141,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 }
 
 pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                          -> Box<base::MacResult> {
+                          -> Box<base::MacResult+'static> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
         Some(f) => f,
         None => return DummyResult::expr(sp)
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index 77324632664..1f50eb933bb 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -18,7 +18,7 @@ use parse::token::{keywords, is_keyword};
 pub fn expand_trace_macros(cx: &mut ExtCtxt,
                            sp: Span,
                            tt: &[ast::TokenTree])
-                           -> Box<base::MacResult> {
+                           -> Box<base::MacResult+'static> {
     match tt {
         [ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
             cx.set_trace_macros(true);
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 1eb37abb781..d8f0eb32ad7 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -14,7 +14,6 @@ use ast;
 use codemap::{Span, Spanned, DUMMY_SP};
 use ext::base::{ExtCtxt, MacResult, MacroDef};
 use ext::base::{NormalTT, TTMacroExpander};
-use ext::base;
 use ext::tt::macro_parser::{Success, Error, Failure};
 use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
 use ext::tt::macro_parser::{parse, parse_or_else};
@@ -113,11 +112,11 @@ struct MacroRulesMacroExpander {
 }
 
 impl TTMacroExpander for MacroRulesMacroExpander {
-    fn expand(&self,
-              cx: &mut ExtCtxt,
-              sp: Span,
-              arg: &[ast::TokenTree])
-              -> Box<MacResult> {
+    fn expand<'cx>(&self,
+                   cx: &'cx mut ExtCtxt,
+                   sp: Span,
+                   arg: &[ast::TokenTree])
+                   -> Box<MacResult+'cx> {
         generic_extension(cx,
                           sp,
                           self.name,
@@ -137,13 +136,13 @@ impl MacResult for MacroRulesDefiner {
 }
 
 /// Given `lhses` and `rhses`, this is the new macro we create
-fn generic_extension(cx: &ExtCtxt,
-                     sp: Span,
-                     name: Ident,
-                     arg: &[ast::TokenTree],
-                     lhses: &[Rc<NamedMatch>],
-                     rhses: &[Rc<NamedMatch>])
-                     -> Box<MacResult> {
+fn generic_extension<'cx>(cx: &'cx ExtCtxt,
+                          sp: Span,
+                          name: Ident,
+                          arg: &[ast::TokenTree],
+                          lhses: &[Rc<NamedMatch>],
+                          rhses: &[Rc<NamedMatch>])
+                          -> Box<MacResult+'cx> {
     if cx.trace_macros() {
         println!("{}! {} {} {}",
                  token::get_ident(name),
@@ -195,7 +194,7 @@ fn generic_extension(cx: &ExtCtxt,
                 // Weird, but useful for X-macros.
                 return box ParserAnyMacro {
                     parser: RefCell::new(p),
-                } as Box<MacResult>
+                } as Box<MacResult+'cx>
               }
               Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                 best_fail_spot = sp;
@@ -213,11 +212,11 @@ fn generic_extension(cx: &ExtCtxt,
 /// This procedure performs the expansion of the
 /// macro_rules! macro. It parses the RHS and adds
 /// an extension to the current context.
-pub fn add_new_extension(cx: &mut ExtCtxt,
-                         sp: Span,
-                         name: Ident,
-                         arg: Vec<ast::TokenTree> )
-                         -> Box<base::MacResult> {
+pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
+                              sp: Span,
+                              name: Ident,
+                              arg: Vec<ast::TokenTree> )
+                              -> Box<MacResult+'cx> {
     // these spans won't matter, anyways
     fn ms(m: Matcher_) -> Matcher {
         Spanned {
@@ -274,5 +273,5 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
             name: token::get_ident(name).to_string(),
             ext: NormalTT(exp, Some(sp))
         }))
-    } as Box<MacResult>
+    } as Box<MacResult+'cx>
 }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 4a0787aeb9e..be1c0d96711 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -227,15 +227,20 @@ pub trait Folder {
         noop_fold_variant_arg(va, self)
     }
 
-    fn fold_ty_param_bound(&mut self, tpb: &TyParamBound) -> TyParamBound {
-        noop_fold_ty_param_bound(tpb, self)
-    }
-
     fn fold_opt_bounds(&mut self, b: &Option<OwnedSlice<TyParamBound>>)
                        -> Option<OwnedSlice<TyParamBound>> {
         noop_fold_opt_bounds(b, self)
     }
 
+    fn fold_bounds(&mut self, b: &OwnedSlice<TyParamBound>)
+                       -> OwnedSlice<TyParamBound> {
+        noop_fold_bounds(b, self)
+    }
+
+    fn fold_ty_param_bound(&mut self, tpb: &TyParamBound) -> TyParamBound {
+        noop_fold_ty_param_bound(tpb, self)
+    }
+
     fn fold_mt(&mut self, mt: &MutTy) -> MutTy {
         noop_fold_mt(mt, self)
     }
@@ -349,20 +354,20 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
         TyRptr(ref region, ref mt) => {
             TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
         }
-        TyClosure(ref f, ref region) => {
+        TyClosure(ref f) => {
             TyClosure(box(GC) ClosureTy {
                 fn_style: f.fn_style,
                 onceness: f.onceness,
-                bounds: fld.fold_opt_bounds(&f.bounds),
+                bounds: fld.fold_bounds(&f.bounds),
                 decl: fld.fold_fn_decl(&*f.decl),
                 lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
-            }, fld.fold_opt_lifetime(region))
+            })
         }
         TyProc(ref f) => {
             TyProc(box(GC) ClosureTy {
                 fn_style: f.fn_style,
                 onceness: f.onceness,
-                bounds: fld.fold_opt_bounds(&f.bounds),
+                bounds: fld.fold_bounds(&f.bounds),
                 decl: fld.fold_fn_decl(&*f.decl),
                 lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
             })
@@ -648,14 +653,13 @@ pub fn noop_fold_ty_param_bound<T: Folder>(tpb: &TyParamBound, fld: &mut T)
                                            -> TyParamBound {
     match *tpb {
         TraitTyParamBound(ref ty) => TraitTyParamBound(fld.fold_trait_ref(ty)),
-        StaticRegionTyParamBound => StaticRegionTyParamBound,
+        RegionTyParamBound(ref lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
         UnboxedFnTyParamBound(ref unboxed_function_type) => {
             UnboxedFnTyParamBound(UnboxedFnTy {
                 decl: fld.fold_fn_decl(&*unboxed_function_type.decl),
                 kind: unboxed_function_type.kind,
             })
         }
-        OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
     }
 }
 
@@ -664,7 +668,7 @@ pub fn noop_fold_ty_param<T: Folder>(tp: &TyParam, fld: &mut T) -> TyParam {
     TyParam {
         ident: tp.ident,
         id: id,
-        bounds: tp.bounds.map(|x| fld.fold_ty_param_bound(x)),
+        bounds: fld.fold_bounds(&tp.bounds),
         unbound: tp.unbound.as_ref().map(|x| fld.fold_ty_param_bound(x)),
         default: tp.default.map(|x| fld.fold_ty(x)),
         span: tp.span
@@ -792,11 +796,12 @@ pub fn noop_fold_mt<T: Folder>(mt: &MutTy, folder: &mut T) -> MutTy {
 
 pub fn noop_fold_opt_bounds<T: Folder>(b: &Option<OwnedSlice<TyParamBound>>, folder: &mut T)
                               -> Option<OwnedSlice<TyParamBound>> {
-    b.as_ref().map(|bounds| {
-        bounds.map(|bound| {
-            folder.fold_ty_param_bound(bound)
-        })
-    })
+    b.as_ref().map(|bounds| folder.fold_bounds(bounds))
+}
+
+fn noop_fold_bounds<T: Folder>(bounds: &TyParamBounds, folder: &mut T)
+                          -> TyParamBounds {
+    bounds.map(|bound| folder.fold_ty_param_bound(bound))
 }
 
 pub fn noop_fold_variant_arg<T: Folder>(va: &VariantArg, folder: &mut T) -> VariantArg {
@@ -889,7 +894,8 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
                                }).collect()
             )
         }
-        ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
+        ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
+            let bounds = folder.fold_bounds(bounds);
             let methods = methods.iter().flat_map(|method| {
                 let r = match *method {
                     RequiredMethod(ref m) => {
@@ -911,7 +917,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
             }).collect();
             ItemTrait(folder.fold_generics(generics),
                       unbound.clone(),
-                      traits.iter().map(|p| folder.fold_trait_ref(p)).collect(),
+                      bounds,
                       methods)
         }
         ItemMac(ref m) => ItemMac(folder.fold_mac(m)),
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 291c876082f..9bbd6b2a36e 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -25,6 +25,7 @@
 
 #![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
 #![feature(quote, struct_variant, unsafe_destructor, import_shadowing)]
+#![feature(issue_5723_bootstrap)]
 #![allow(deprecated)]
 
 // NOTE(stage0, pcwalton): Remove after snapshot.
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 816700681cf..37bda15ac2c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -12,7 +12,7 @@
 
 use abi;
 use ast::{BareFnTy, ClosureTy};
-use ast::{StaticRegionTyParamBound, OtherRegionTyParamBound, TraitTyParamBound};
+use ast::{RegionTyParamBound, TraitTyParamBound};
 use ast::{ProvidedMethod, Public, FnStyle};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
@@ -70,7 +70,7 @@ use parse;
 use parse::attr::ParserAttr;
 use parse::classify;
 use parse::common::{SeqSep, seq_sep_none};
-use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
+use parse::common::{seq_sep_trailing_allowed};
 use parse::lexer::Reader;
 use parse::lexer::TokenAndSpan;
 use parse::obsolete::*;
@@ -120,7 +120,7 @@ pub enum PathParsingMode {
 /// A path paired with optional type bounds.
 pub struct PathAndBounds {
     pub path: ast::Path,
-    pub bounds: Option<OwnedSlice<TyParamBound>>,
+    pub bounds: Option<ast::TyParamBounds>,
 }
 
 enum ItemOrViewItem {
@@ -309,7 +309,7 @@ pub struct Parser<'a> {
     pub tokens_consumed: uint,
     pub restriction: restriction,
     pub quote_depth: uint, // not (yet) related to the quasiquoter
-    pub reader: Box<Reader>,
+    pub reader: Box<Reader+'a>,
     pub interner: Rc<token::IdentInterner>,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
@@ -346,8 +346,11 @@ fn real_token(rdr: &mut Reader) -> TokenAndSpan {
 }
 
 impl<'a> Parser<'a> {
-    pub fn new(sess: &'a ParseSess, cfg: ast::CrateConfig,
-               mut rdr: Box<Reader>) -> Parser<'a> {
+    pub fn new(sess: &'a ParseSess,
+               cfg: ast::CrateConfig,
+               mut rdr: Box<Reader+'a>)
+               -> Parser<'a>
+    {
         let tok0 = real_token(rdr);
         let span = tok0.sp;
         let placeholder = TokenAndSpan {
@@ -1073,14 +1076,7 @@ impl<'a> Parser<'a> {
         };
 
         let (inputs, variadic) = self.parse_fn_args(false, false);
-        let bounds = {
-            if self.eat(&token::COLON) {
-                let (_, bounds) = self.parse_ty_param_bounds(false);
-                Some(bounds)
-            } else {
-                None
-            }
-        };
+        let bounds = self.parse_colon_then_ty_param_bounds();
         let (ret_style, ret_ty) = self.parse_ret_ty();
         let decl = P(FnDecl {
             inputs: inputs,
@@ -1168,14 +1164,7 @@ impl<'a> Parser<'a> {
             (optional_unboxed_closure_kind, inputs)
         };
 
-        let (region, bounds) = {
-            if self.eat(&token::COLON) {
-                let (region, bounds) = self.parse_ty_param_bounds(true);
-                (region, Some(bounds))
-            } else {
-                (None, None)
-            }
-        };
+        let bounds = self.parse_colon_then_ty_param_bounds();
 
         let (return_style, output) = self.parse_ret_ty();
         let decl = P(FnDecl {
@@ -1199,7 +1188,7 @@ impl<'a> Parser<'a> {
                     bounds: bounds,
                     decl: decl,
                     lifetimes: lifetime_defs,
-                }, region)
+                })
             }
         }
     }
@@ -1687,7 +1676,7 @@ impl<'a> Parser<'a> {
             Some(INTERPOLATED(token::NtPath(box path))) => {
                 return PathAndBounds {
                     path: path,
-                    bounds: None,
+                    bounds: None
                 }
             }
             _ => {}
@@ -1744,25 +1733,31 @@ impl<'a> Parser<'a> {
             }
         }
 
-        // Next, parse a plus and bounded type parameters, if applicable.
-        let bounds = if mode == LifetimeAndTypesAndBounds {
-            let bounds = {
-                if self.eat(&token::BINOP(token::PLUS)) {
-                    let (_, bounds) = self.parse_ty_param_bounds(false);
-                    if bounds.len() == 0 {
-                        let last_span = self.last_span;
-                        self.span_err(last_span,
-                                      "at least one type parameter bound \
-                                       must be specified after the `+`");
-                    }
-                    Some(bounds)
-                } else {
-                    None
+        // Next, parse a plus and bounded type parameters, if
+        // applicable. We need to remember whether the separate was
+        // present for later, because in some contexts it's a parse
+        // error.
+        let opt_bounds = {
+            if mode == LifetimeAndTypesAndBounds &&
+                self.eat(&token::BINOP(token::PLUS))
+            {
+                let bounds = self.parse_ty_param_bounds();
+
+                // For some reason that I do not fully understand, we
+                // do not permit an empty list in the case where it is
+                // introduced by a `+`, but we do for `:` and other
+                // separators. -nmatsakis
+                if bounds.len() == 0 {
+                    let last_span = self.last_span;
+                    self.span_err(last_span,
+                                  "at least one type parameter bound \
+                                   must be specified");
                 }
-            };
-            bounds
-        } else {
-            None
+
+                Some(bounds)
+            } else {
+                None
+            }
         };
 
         // Assemble the span.
@@ -1775,7 +1770,7 @@ impl<'a> Parser<'a> {
                 global: is_global,
                 segments: segments,
             },
-            bounds: bounds,
+            bounds: opt_bounds,
         }
     }
 
@@ -3604,45 +3599,34 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// matches optbounds = ( ( : ( boundseq )? )? )
-    /// where   boundseq  = ( bound + boundseq ) | bound
-    /// and     bound     = 'static | ty
-    /// Returns "None" if there's no colon (e.g. "T");
-    /// Returns "Some(Empty)" if there's a colon but nothing after (e.g. "T:")
-    /// Returns "Some(stuff)" otherwise (e.g. "T:stuff").
-    /// NB: The None/Some distinction is important for issue #7264.
-    ///
-    /// Note that the `allow_any_lifetime` argument is a hack for now while the
-    /// AST doesn't support arbitrary lifetimes in bounds on type parameters. In
-    /// the future, this flag should be removed, and the return value of this
-    /// function should be Option<~[TyParamBound]>
-    fn parse_ty_param_bounds(&mut self, allow_any_lifetime: bool)
-                             -> (Option<ast::Lifetime>,
-                                 OwnedSlice<TyParamBound>) {
-        let mut ret_lifetime = None;
+    // Parses a sequence of bounds if a `:` is found,
+    // otherwise returns empty list.
+    fn parse_colon_then_ty_param_bounds(&mut self)
+                                        -> OwnedSlice<TyParamBound>
+    {
+        if !self.eat(&token::COLON) {
+            OwnedSlice::empty()
+        } else {
+            self.parse_ty_param_bounds()
+        }
+    }
+
+    // matches bounds    = ( boundseq )?
+    // where   boundseq  = ( bound + boundseq ) | bound
+    // and     bound     = 'region | ty
+    // NB: The None/Some distinction is important for issue #7264.
+    fn parse_ty_param_bounds(&mut self)
+                             -> OwnedSlice<TyParamBound>
+    {
         let mut result = vec!();
         loop {
             match self.token {
                 token::LIFETIME(lifetime) => {
-                    let lifetime_interned_string = token::get_ident(lifetime);
-                    if lifetime_interned_string.equiv(&("'static")) {
-                        result.push(StaticRegionTyParamBound);
-                        if allow_any_lifetime && ret_lifetime.is_none() {
-                            ret_lifetime = Some(ast::Lifetime {
-                                id: ast::DUMMY_NODE_ID,
-                                span: self.span,
-                                name: lifetime.name
-                            });
-                        }
-                    } else if allow_any_lifetime && ret_lifetime.is_none() {
-                        ret_lifetime = Some(ast::Lifetime {
-                            id: ast::DUMMY_NODE_ID,
-                            span: self.span,
-                            name: lifetime.name
-                        });
-                    } else {
-                        result.push(OtherRegionTyParamBound(self.span));
-                    }
+                    result.push(RegionTyParamBound(ast::Lifetime {
+                        id: ast::DUMMY_NODE_ID,
+                        span: self.span,
+                        name: lifetime.name
+                    }));
                     self.bump();
                 }
                 token::MOD_SEP | token::IDENT(..) => {
@@ -3662,7 +3646,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        return (ret_lifetime, OwnedSlice::from_vec(result));
+        return OwnedSlice::from_vec(result);
     }
 
     fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef {
@@ -3699,16 +3683,7 @@ impl<'a> Parser<'a> {
             ident = self.parse_ident();
         }
 
-        let opt_bounds = {
-            if self.eat(&token::COLON) {
-                let (_, bounds) = self.parse_ty_param_bounds(false);
-                Some(bounds)
-            } else {
-                None
-            }
-        };
-        // For typarams we don't care about the difference b/w "<T>" and "<T:>".
-        let bounds = opt_bounds.unwrap_or_default();
+        let bounds = self.parse_colon_then_ty_param_bounds();
 
         let default = if self.token == token::EQ {
             self.bump();
@@ -3797,7 +3772,7 @@ impl<'a> Parser<'a> {
             };
             self.expect(&token::COLON);
 
-            let (_, bounds) = self.parse_ty_param_bounds(false);
+            let bounds = self.parse_ty_param_bounds();
             let hi = self.span.hi;
             let span = mk_sp(lo, hi);
 
@@ -4273,19 +4248,13 @@ impl<'a> Parser<'a> {
         let mut tps = self.parse_generics();
         let sized = self.parse_for_sized();
 
-        // Parse traits, if necessary.
-        let traits;
-        if self.token == token::COLON {
-            self.bump();
-            traits = self.parse_trait_ref_list(&token::LBRACE);
-        } else {
-            traits = Vec::new();
-        }
+        // Parse supertrait bounds.
+        let bounds = self.parse_colon_then_ty_param_bounds();
 
         self.parse_where_clause(&mut tps);
 
         let meths = self.parse_trait_methods();
-        (ident, ItemTrait(tps, sized, traits, meths), None)
+        (ident, ItemTrait(tps, sized, bounds, meths), None)
     }
 
     fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
@@ -4319,12 +4288,10 @@ impl<'a> Parser<'a> {
             // New-style trait. Reinterpret the type as a trait.
             let opt_trait_ref = match ty.node {
                 TyPath(ref path, None, node_id) => {
-                    Some(TraitRef {
-                        path: /* bad */ (*path).clone(),
-                        ref_id: node_id
-                    })
+                    Some(TraitRef { path: (*path).clone(),
+                                    ref_id: node_id })
                 }
-                TyPath(..) => {
+                TyPath(_, Some(_), _) => {
                     self.span_err(ty.span,
                                   "bounded traits are only valid in type position");
                     None
@@ -4359,15 +4326,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parse B + C<String,int> + D
-    fn parse_trait_ref_list(&mut self, ket: &token::Token) -> Vec<TraitRef> {
-        self.parse_seq_to_before_end(
-            ket,
-            seq_sep_trailing_disallowed(token::BINOP(token::PLUS)),
-            |p| p.parse_trait_ref()
-        )
-    }
-
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo {
         let class_name = self.parse_ident();
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index f28e6829b00..70da4e11961 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -155,7 +155,7 @@ pub struct PrintStackElem {
 
 static SIZE_INFINITY: int = 0xffff;
 
-pub fn mk_printer(out: Box<io::Writer>, linewidth: uint) -> Printer {
+pub fn mk_printer(out: Box<io::Writer+'static>, linewidth: uint) -> Printer {
     // Yes 3, it makes the ring buffers big enough to never
     // fall behind.
     let n: uint = 3 * linewidth;
@@ -260,7 +260,7 @@ pub fn mk_printer(out: Box<io::Writer>, linewidth: uint) -> Printer {
 /// the method called 'pretty_print', and the 'PRINT' process is the method
 /// called 'print'.
 pub struct Printer {
-    pub out: Box<io::Writer>,
+    pub out: Box<io::Writer+'static>,
     buf_len: uint,
     /// Width of lines we're constrained to
     margin: int,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 41f95fa75f5..da265d81250 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -10,8 +10,8 @@
 
 use abi;
 use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
-use ast::{FnUnboxedClosureKind, MethodImplItem, P, OtherRegionTyParamBound};
-use ast::{StaticRegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
+use ast::{FnUnboxedClosureKind, MethodImplItem, P};
+use ast::{RegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
 use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
 use ast;
 use ast_util;
@@ -60,16 +60,16 @@ pub struct State<'a> {
     literals: Option<Vec<comments::Literal> >,
     cur_cmnt_and_lit: CurrentCommentAndLiteral,
     boxes: Vec<pp::Breaks>,
-    ann: &'a PpAnn,
+    ann: &'a PpAnn+'a,
     encode_idents_with_hygiene: bool,
 }
 
-pub fn rust_printer(writer: Box<io::Writer>) -> State<'static> {
+pub fn rust_printer(writer: Box<io::Writer+'static>) -> State<'static> {
     static NO_ANN: NoAnn = NoAnn;
     rust_printer_annotated(writer, &NO_ANN)
 }
 
-pub fn rust_printer_annotated<'a>(writer: Box<io::Writer>,
+pub fn rust_printer_annotated<'a>(writer: Box<io::Writer+'static>,
                                   ann: &'a PpAnn) -> State<'a> {
     State {
         s: pp::mk_printer(writer, default_columns),
@@ -98,7 +98,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        krate: &ast::Crate,
                        filename: String,
                        input: &mut io::Reader,
-                       out: Box<io::Writer>,
+                       out: Box<io::Writer+'static>,
                        ann: &'a PpAnn,
                        is_expanded: bool) -> IoResult<()> {
     let mut s = State::new_from_input(cm,
@@ -118,7 +118,7 @@ impl<'a> State<'a> {
                           span_diagnostic: &diagnostic::SpanHandler,
                           filename: String,
                           input: &mut io::Reader,
-                          out: Box<io::Writer>,
+                          out: Box<io::Writer+'static>,
                           ann: &'a PpAnn,
                           is_expanded: bool) -> State<'a> {
         let (cmnts, lits) = comments::gather_comments_and_literals(
@@ -138,7 +138,7 @@ impl<'a> State<'a> {
     }
 
     pub fn new(cm: &'a CodeMap,
-               out: Box<io::Writer>,
+               out: Box<io::Writer+'static>,
                ann: &'a PpAnn,
                comments: Option<Vec<comments::Comment>>,
                literals: Option<Vec<comments::Literal>>) -> State<'a> {
@@ -594,17 +594,16 @@ impl<'a> State<'a> {
                 };
                 try!(self.print_ty_fn(Some(f.abi),
                                       None,
-                                      &None,
                                       f.fn_style,
                                       ast::Many,
                                       &*f.decl,
                                       None,
-                                      &None,
+                                      &OwnedSlice::empty(),
                                       Some(&generics),
                                       None,
                                       None));
             }
-            ast::TyClosure(f, ref region) => {
+            ast::TyClosure(f) => {
                 let generics = ast::Generics {
                     lifetimes: f.lifetimes.clone(),
                     ty_params: OwnedSlice::empty(),
@@ -615,7 +614,6 @@ impl<'a> State<'a> {
                 };
                 try!(self.print_ty_fn(None,
                                       Some('&'),
-                                      region,
                                       f.fn_style,
                                       f.onceness,
                                       &*f.decl,
@@ -636,7 +634,6 @@ impl<'a> State<'a> {
                 };
                 try!(self.print_ty_fn(None,
                                       Some('~'),
-                                      &None,
                                       f.fn_style,
                                       f.onceness,
                                       &*f.decl,
@@ -649,12 +646,11 @@ impl<'a> State<'a> {
             ast::TyUnboxedFn(f) => {
                 try!(self.print_ty_fn(None,
                                       None,
-                                      &None,
                                       ast::NormalFn,
                                       ast::Many,
                                       &*f.decl,
                                       None,
-                                      &None,
+                                      &OwnedSlice::empty(),
                                       None,
                                       None,
                                       Some(f.kind)));
@@ -837,7 +833,7 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
+            ast::ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "trait").as_slice()));
                 try!(self.print_ident(item.ident));
@@ -851,16 +847,7 @@ impl<'a> State<'a> {
                     }
                     _ => {}
                 }
-                if traits.len() != 0u {
-                    try!(word(&mut self.s, ":"));
-                    for (i, trait_) in traits.iter().enumerate() {
-                        try!(self.nbsp());
-                        if i != 0 {
-                            try!(self.word_space("+"));
-                        }
-                        try!(self.print_path(&trait_.path, false));
-                    }
-                }
+                try!(self.print_bounds(":", bounds));
                 try!(self.print_where_clause(generics));
                 try!(word(&mut self.s, " "));
                 try!(self.bopen());
@@ -1073,12 +1060,11 @@ impl<'a> State<'a> {
         try!(self.print_outer_attributes(m.attrs.as_slice()));
         try!(self.print_ty_fn(None,
                               None,
-                              &None,
                               m.fn_style,
                               ast::Many,
                               &*m.decl,
                               Some(m.ident),
-                              &None,
+                              &OwnedSlice::empty(),
                               Some(&m.generics),
                               Some(m.explicit_self.node),
                               None));
@@ -1808,7 +1794,7 @@ impl<'a> State<'a> {
 
         match *opt_bounds {
             None => Ok(()),
-            Some(ref bounds) => self.print_bounds(&None, bounds, true, true),
+            Some(ref bounds) => self.print_bounds("+", bounds)
         }
     }
 
@@ -2132,30 +2118,12 @@ impl<'a> State<'a> {
     }
 
     pub fn print_bounds(&mut self,
-                        region: &Option<ast::Lifetime>,
-                        bounds: &OwnedSlice<ast::TyParamBound>,
-                        print_colon_anyway: bool,
-                        print_plus_before_bounds: bool)
+                        prefix: &str,
+                        bounds: &OwnedSlice<ast::TyParamBound>)
                         -> IoResult<()> {
-        let separator = if print_plus_before_bounds {
-            "+"
-        } else {
-            ":"
-        };
-        if !bounds.is_empty() || region.is_some() {
-            try!(word(&mut self.s, separator));
+        if !bounds.is_empty() {
+            try!(word(&mut self.s, prefix));
             let mut first = true;
-            match *region {
-                Some(ref lt) => {
-                    let token = token::get_name(lt.name);
-                    if token.get() != "'static" {
-                        try!(self.nbsp());
-                        first = false;
-                        try!(self.print_lifetime(lt));
-                    }
-                }
-                None => {}
-            }
             for bound in bounds.iter() {
                 try!(self.nbsp());
                 if first {
@@ -2165,27 +2133,27 @@ impl<'a> State<'a> {
                 }
 
                 try!(match *bound {
-                    TraitTyParamBound(ref tref) => self.print_trait_ref(tref),
-                    StaticRegionTyParamBound => word(&mut self.s, "'static"),
+                    TraitTyParamBound(ref tref) => {
+                        self.print_trait_ref(tref)
+                    }
+                    RegionTyParamBound(ref lt) => {
+                        self.print_lifetime(lt)
+                    }
                     UnboxedFnTyParamBound(ref unboxed_function_type) => {
                         self.print_ty_fn(None,
                                          None,
-                                         &None,
                                          ast::NormalFn,
                                          ast::Many,
                                          &*unboxed_function_type.decl,
                                          None,
-                                         &None,
+                                         &OwnedSlice::empty(),
                                          None,
                                          None,
                                          Some(unboxed_function_type.kind))
                     }
-                    OtherRegionTyParamBound(_) => Ok(())
                 })
             }
             Ok(())
-        } else if print_colon_anyway {
-            word(&mut self.s, separator)
         } else {
             Ok(())
         }
@@ -2212,23 +2180,29 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    fn print_type_parameters(&mut self,
-                             lifetimes: &[ast::LifetimeDef],
-                             ty_params: &[ast::TyParam])
-                             -> IoResult<()> {
-        let total = lifetimes.len() + ty_params.len();
+    pub fn print_generics(&mut self,
+                          generics: &ast::Generics)
+                          -> IoResult<()>
+    {
+        let total = generics.lifetimes.len() + generics.ty_params.len();
+        if total == 0 {
+            return Ok(());
+        }
+
+        try!(word(&mut self.s, "<"));
+
         let mut ints = Vec::new();
         for i in range(0u, total) {
             ints.push(i);
         }
 
-        self.commasep(Inconsistent, ints.as_slice(), |s, &idx| {
-            if idx < lifetimes.len() {
-                let lifetime = &lifetimes[idx];
+        try!(self.commasep(Inconsistent, ints.as_slice(), |s, &idx| {
+            if idx < generics.lifetimes.len() {
+                let lifetime = generics.lifetimes.get(idx);
                 s.print_lifetime_def(lifetime)
             } else {
-                let idx = idx - lifetimes.len();
-                let param = &ty_params[idx];
+                let idx = idx - generics.lifetimes.len();
+                let param = generics.ty_params.get(idx);
                 match param.unbound {
                     Some(TraitTyParamBound(ref tref)) => {
                         try!(s.print_trait_ref(tref));
@@ -2237,10 +2211,7 @@ impl<'a> State<'a> {
                     _ => {}
                 }
                 try!(s.print_ident(param.ident));
-                try!(s.print_bounds(&None,
-                                    &param.bounds,
-                                    false,
-                                    false));
+                try!(s.print_bounds(":", &param.bounds));
                 match param.default {
                     Some(ref default) => {
                         try!(space(&mut s.s));
@@ -2250,19 +2221,10 @@ impl<'a> State<'a> {
                     _ => Ok(())
                 }
             }
-        })
-    }
+        }));
 
-    pub fn print_generics(&mut self, generics: &ast::Generics)
-                          -> IoResult<()> {
-        if generics.lifetimes.len() + generics.ty_params.len() > 0 {
-            try!(word(&mut self.s, "<"));
-            try!(self.print_type_parameters(generics.lifetimes.as_slice(),
-                                            generics.ty_params.as_slice()));
-            word(&mut self.s, ">")
-        } else {
-            Ok(())
-        }
+        try!(word(&mut self.s, ">"));
+        Ok(())
     }
 
     pub fn print_where_clause(&mut self, generics: &ast::Generics)
@@ -2283,7 +2245,7 @@ impl<'a> State<'a> {
             }
 
             try!(self.print_ident(predicate.ident));
-            try!(self.print_bounds(&None, &predicate.bounds, false, false));
+            try!(self.print_bounds(":", &predicate.bounds));
         }
 
         Ok(())
@@ -2421,12 +2383,11 @@ impl<'a> State<'a> {
     pub fn print_ty_fn(&mut self,
                        opt_abi: Option<abi::Abi>,
                        opt_sigil: Option<char>,
-                       opt_region: &Option<ast::Lifetime>,
                        fn_style: ast::FnStyle,
                        onceness: ast::Onceness,
                        decl: &ast::FnDecl,
                        id: Option<ast::Ident>,
-                       opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
+                       bounds: &OwnedSlice<ast::TyParamBound>,
                        generics: Option<&ast::Generics>,
                        opt_explicit_self: Option<ast::ExplicitSelf_>,
                        opt_unboxed_closure_kind:
@@ -2495,9 +2456,7 @@ impl<'a> State<'a> {
             try!(self.pclose());
         }
 
-        opt_bounds.as_ref().map(|bounds| {
-            self.print_bounds(opt_region, bounds, true, false)
-        });
+        try!(self.print_bounds(":", bounds));
 
         try!(self.maybe_print_comment(decl.output.span.lo));
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6c6f59f0df6..7a35d82b0e4 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -298,13 +298,9 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                                      item.id,
                                      env.clone())
         }
-        ItemTrait(ref generics, _, ref trait_paths, ref methods) => {
+        ItemTrait(ref generics, _, ref bounds, ref methods) => {
             visitor.visit_generics(generics, env.clone());
-            for trait_path in trait_paths.iter() {
-                visitor.visit_path(&trait_path.path,
-                                   trait_path.ref_id,
-                                   env.clone())
-            }
+            walk_ty_param_bounds(visitor, bounds, env.clone());
             for method in methods.iter() {
                 visitor.visit_trait_item(method, env.clone())
             }
@@ -375,18 +371,13 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
                 visitor.visit_ty(&*tuple_element_type, env.clone())
             }
         }
-        TyClosure(ref function_declaration, ref region) => {
+        TyClosure(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty, env.clone())
             }
             visitor.visit_ty(&*function_declaration.decl.output, env.clone());
-            for bounds in function_declaration.bounds.iter() {
-                walk_ty_param_bounds(visitor, bounds, env.clone())
-            }
-            visitor.visit_opt_lifetime_ref(
-                typ.span,
-                region,
-                env.clone());
+            walk_ty_param_bounds(visitor, &function_declaration.bounds,
+                                 env.clone());
             walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                 env.clone());
         }
@@ -395,9 +386,8 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
                 visitor.visit_ty(&*argument.ty, env.clone())
             }
             visitor.visit_ty(&*function_declaration.decl.output, env.clone());
-            for bounds in function_declaration.bounds.iter() {
-                walk_ty_param_bounds(visitor, bounds, env.clone())
-            }
+            walk_ty_param_bounds(visitor, &function_declaration.bounds,
+                                 env.clone());
             walk_lifetime_decls(visitor, &function_declaration.lifetimes,
                                 env.clone());
         }
@@ -415,10 +405,13 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
             }
             visitor.visit_ty(&*function_declaration.decl.output, env.clone());
         }
-        TyPath(ref path, ref bounds, id) => {
+        TyPath(ref path, ref opt_bounds, id) => {
             visitor.visit_path(path, id, env.clone());
-            for bounds in bounds.iter() {
-                walk_ty_param_bounds(visitor, bounds, env.clone())
+            match *opt_bounds {
+                Some(ref bounds) => {
+                    walk_ty_param_bounds(visitor, bounds, env.clone());
+                }
+                None => { }
             }
         }
         TyFixedLengthVec(ref ty, ref expression) => {
@@ -532,7 +525,6 @@ pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V,
             TraitTyParamBound(ref typ) => {
                 walk_trait_ref_helper(visitor, typ, env.clone())
             }
-            StaticRegionTyParamBound => {}
             UnboxedFnTyParamBound(ref function_declaration) => {
                 for argument in function_declaration.decl.inputs.iter() {
                     visitor.visit_ty(&*argument.ty, env.clone())
@@ -540,7 +532,9 @@ pub fn walk_ty_param_bounds<E: Clone, V: Visitor<E>>(visitor: &mut V,
                 visitor.visit_ty(&*function_declaration.decl.output,
                                  env.clone());
             }
-            OtherRegionTyParamBound(..) => {}
+            RegionTyParamBound(ref lifetime) => {
+                visitor.visit_lifetime_ref(lifetime, env.clone());
+            }
         }
     }
 }