about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2015-03-10 12:28:44 +0200
committerEduard Burtescu <edy.burt@gmail.com>2015-03-11 23:39:16 +0200
commitf98b1763140e4c9b0f122bde2f5cbd24227554a2 (patch)
tree70e9da4c25e7f110b2ac58f3c6500dbb309bf772 /src/libsyntax
parent98491827b920884e4ea1182dcacce2a650dde861 (diff)
downloadrust-f98b1763140e4c9b0f122bde2f5cbd24227554a2.tar.gz
rust-f98b1763140e4c9b0f122bde2f5cbd24227554a2.zip
syntax: gather common fields of impl & trait items into their respective types.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs66
-rw-r--r--src/libsyntax/ast_map/blocks.rs24
-rw-r--r--src/libsyntax/ast_map/mod.rs253
-rw-r--r--src/libsyntax/ast_util.rs39
-rw-r--r--src/libsyntax/config.rs23
-rw-r--r--src/libsyntax/ext/base.rs50
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs46
-rw-r--r--src/libsyntax/ext/expand.rs145
-rw-r--r--src/libsyntax/ext/quote.rs11
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs3
-rw-r--r--src/libsyntax/fold.rs165
-rw-r--r--src/libsyntax/parse/parser.rs121
-rw-r--r--src/libsyntax/print/pprust.rs115
-rw-r--r--src/libsyntax/visit.rs127
14 files changed, 459 insertions, 729 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index fafcc056ded..bc1767fa3a4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -22,7 +22,7 @@ pub use self::Expr_::*;
 pub use self::FloatTy::*;
 pub use self::FunctionRetTy::*;
 pub use self::ForeignItem_::*;
-pub use self::ImplItem::*;
+pub use self::ImplItem_::*;
 pub use self::InlinedItem::*;
 pub use self::IntTy::*;
 pub use self::Item_::*;
@@ -33,7 +33,7 @@ pub use self::LocalSource::*;
 pub use self::Mac_::*;
 pub use self::MacStmtStyle::*;
 pub use self::MetaItem_::*;
-pub use self::Method_::*;
+pub use self::Method::*;
 pub use self::Mutability::*;
 pub use self::Pat_::*;
 pub use self::PathListItem_::*;
@@ -44,7 +44,7 @@ pub use self::Stmt_::*;
 pub use self::StrStyle::*;
 pub use self::StructFieldKind::*;
 pub use self::TokenTree::*;
-pub use self::TraitItem::*;
+pub use self::TraitItem_::*;
 pub use self::Ty_::*;
 pub use self::TyParamBound::*;
 pub use self::UintTy::*;
@@ -1062,16 +1062,11 @@ pub struct TypeField {
 /// one without a default implementation
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TypeMethod {
-    pub ident: Ident,
-    pub attrs: Vec<Attribute>,
     pub unsafety: Unsafety,
     pub abi: Abi,
     pub decl: P<FnDecl>,
     pub generics: Generics,
     pub explicit_self: ExplicitSelf,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
 }
 
 /// Represents a method declaration in a trait declaration, possibly including
@@ -1079,32 +1074,35 @@ pub struct TypeMethod {
 /// doesn't have an implementation, just a signature) or provided (meaning it
 /// has a default implementation).
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitItem {
-    RequiredMethod(TypeMethod),
-    ProvidedMethod(Method),
-    TypeTraitItem(AssociatedType),
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum ImplItem {
-    MethodImplItem(Method),
-    TypeImplItem(Typedef),
+pub struct TraitItem {
+    pub id: NodeId,
+    pub ident: Ident,
+    pub attrs: Vec<Attribute>,
+    pub node: TraitItem_,
+    pub span: Span,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct AssociatedType {
-    pub attrs: Vec<Attribute>,
-    pub ty_param: TyParam,
+pub enum TraitItem_ {
+    RequiredMethod(TypeMethod),
+    ProvidedMethod(Method),
+    TypeTraitItem(TyParamBounds, Option<P<Ty>>),
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct Typedef {
+pub struct ImplItem {
     pub id: NodeId,
-    pub span: Span,
     pub ident: Ident,
     pub vis: Visibility,
     pub attrs: Vec<Attribute>,
-    pub typ: P<Ty>,
+    pub node: ImplItem_,
+    pub span: Span,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum ImplItem_ {
+    MethodImplItem(Method),
+    TypeImplItem(P<Ty>),
 }
 
 #[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
@@ -1419,24 +1417,14 @@ pub enum ExplicitSelf_ {
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct Method {
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub node: Method_,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum Method_ {
+pub enum Method {
     /// Represents a method declaration
-    MethDecl(Ident,
-             Generics,
+    MethDecl(Generics,
              Abi,
              ExplicitSelf,
              Unsafety,
              P<FnDecl>,
-             P<Block>,
-             Visibility),
+             P<Block>),
     /// Represents a macro in method position
     MethMac(Mac),
 }
@@ -1726,8 +1714,8 @@ impl ForeignItem_ {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum InlinedItem {
     IIItem(P<Item>),
-    IITraitItem(DefId /* impl id */, TraitItem),
-    IIImplItem(DefId /* impl id */, ImplItem),
+    IITraitItem(DefId /* impl id */, P<TraitItem>),
+    IIImplItem(DefId /* impl id */, P<ImplItem>),
     IIForeign(P<ForeignItem>),
 }
 
diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs
index 8d605ea50cd..053c3153340 100644
--- a/src/libsyntax/ast_map/blocks.rs
+++ b/src/libsyntax/ast_map/blocks.rs
@@ -65,7 +65,7 @@ impl MaybeFnLike for ast::Item {
 
 impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match *self { ast::ProvidedMethod(_) => true, _ => false, }
+        match self.node { ast::ProvidedMethod(_) => true, _ => false, }
     }
 }
 
@@ -156,25 +156,25 @@ impl<'a> FnLikeNode<'a> {
 
     pub fn body(self) -> &'a Block {
         self.handle(|i: ItemFnParts<'a>|  &*i.body,
-                    |m: &'a ast::Method|  m.pe_body(),
+                    |_, _, m: &'a ast::Method, _|  m.pe_body(),
                     |c: ClosureParts<'a>| c.body)
     }
 
     pub fn decl(self) -> &'a FnDecl {
         self.handle(|i: ItemFnParts<'a>|  &*i.decl,
-                    |m: &'a ast::Method|  m.pe_fn_decl(),
+                    |_, _, m: &'a ast::Method, _|  m.pe_fn_decl(),
                     |c: ClosureParts<'a>| c.decl)
     }
 
     pub fn span(self) -> Span {
         self.handle(|i: ItemFnParts|     i.span,
-                    |m: &'a ast::Method| m.span,
+                    |_, _, _: &'a ast::Method, span| span,
                     |c: ClosureParts|    c.span)
     }
 
     pub fn id(self) -> NodeId {
         self.handle(|i: ItemFnParts|     i.id,
-                    |m: &'a ast::Method| m.id,
+                    |id, _, _: &'a ast::Method, _| id,
                     |c: ClosureParts|    c.id)
     }
 
@@ -185,15 +185,15 @@ impl<'a> FnLikeNode<'a> {
         let closure = |_: ClosureParts| {
             visit::FkFnBlock
         };
-        let method = |m: &'a ast::Method| {
-            visit::FkMethod(m.pe_ident(), m.pe_generics(), m)
+        let method = |_, ident, m: &'a ast::Method, _| {
+            visit::FkMethod(ident, m)
         };
         self.handle(item, method, closure)
     }
 
     fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
         I: FnOnce(ItemFnParts<'a>) -> A,
-        M: FnOnce(&'a ast::Method) -> A,
+        M: FnOnce(NodeId, ast::Ident, &'a ast::Method, Span) -> A,
         C: FnOnce(ClosureParts<'a>) -> A,
     {
         match self.node {
@@ -205,13 +205,13 @@ impl<'a> FnLikeNode<'a> {
                     }),
                 _ => panic!("item FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeTraitItem(t) => match *t {
-                ast::ProvidedMethod(ref m) => method(m),
+            ast_map::NodeTraitItem(ti) => match ti.node {
+                ast::ProvidedMethod(ref m) => method(ti.id, ti.ident, m, ti.span),
                 _ => panic!("trait method FnLikeNode that is not fn-like"),
             },
             ast_map::NodeImplItem(ii) => {
-                match *ii {
-                    ast::MethodImplItem(ref m) => method(m),
+                match ii.node {
+                    ast::MethodImplItem(ref m) => method(ii.id, ii.ident, m, ii.span),
                     ast::TypeImplItem(_) => {
                         panic!("impl method FnLikeNode that is not fn-like")
                     }
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 4db6f9bc3c5..606c6b640df 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -14,7 +14,7 @@ use self::MapEntry::*;
 
 use abi;
 use ast::*;
-use ast_util::{self, PostExpansionMethod};
+use ast_util;
 use codemap::{DUMMY_SP, Span, Spanned};
 use fold::Folder;
 use parse::token;
@@ -374,35 +374,8 @@ impl<'ast> Map<'ast> {
                 }
             }
             NodeForeignItem(i) => PathName(i.ident.name),
-            NodeImplItem(ii) => {
-                match *ii {
-                    MethodImplItem(ref m) => {
-                        match m.node {
-                            MethDecl(ident, _, _, _, _, _, _, _) => {
-                                PathName(ident.name)
-                            }
-                            MethMac(_) => {
-                                panic!("no path elem for {:?}", node)
-                            }
-                        }
-                    }
-                    TypeImplItem(ref t) => PathName(t.ident.name),
-                }
-            },
-            NodeTraitItem(tm) => match *tm {
-                RequiredMethod(ref m) => PathName(m.ident.name),
-                ProvidedMethod(ref m) => {
-                    match m.node {
-                        MethDecl(ident, _, _, _, _, _, _, _) => {
-                            PathName(ident.name)
-                        }
-                        MethMac(_) => panic!("no path elem for {:?}", node),
-                    }
-                }
-                TypeTraitItem(ref m) => {
-                    PathName(m.ty_param.ident.name)
-                }
-            },
+            NodeImplItem(ii) => PathName(ii.ident.name),
+            NodeTraitItem(ti) => PathName(ti.ident.name),
             NodeVariant(v) => PathName(v.node.name.name),
             _ => panic!("no path elem for {:?}", node)
         }
@@ -458,21 +431,12 @@ impl<'ast> Map<'ast> {
 
     /// Given a node ID, get a list of of attributes associated with the AST
     /// corresponding to the Node ID
-    pub fn attrs(&self, id: NodeId) -> &[Attribute] {
+    pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] {
         let attrs = match self.find(id) {
             Some(NodeItem(i)) => Some(&i.attrs[..]),
             Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
-            Some(NodeTraitItem(ref tm)) => match **tm {
-                RequiredMethod(ref type_m) => Some(&type_m.attrs[..]),
-                ProvidedMethod(ref m) => Some(&m.attrs[..]),
-                TypeTraitItem(ref typ) => Some(&typ.attrs[..]),
-            },
-            Some(NodeImplItem(ref ii)) => {
-                match **ii {
-                    MethodImplItem(ref m) => Some(&m.attrs[..]),
-                    TypeImplItem(ref t) => Some(&t.attrs[..]),
-                }
-            }
+            Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
+            Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
             Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
@@ -505,19 +469,8 @@ impl<'ast> Map<'ast> {
         let sp = match self.find(id) {
             Some(NodeItem(item)) => item.span,
             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
-            Some(NodeTraitItem(trait_method)) => {
-                match *trait_method {
-                    RequiredMethod(ref type_method) => type_method.span,
-                    ProvidedMethod(ref method) => method.span,
-                    TypeTraitItem(ref typedef) => typedef.ty_param.span,
-                }
-            }
-            Some(NodeImplItem(ref impl_item)) => {
-                match **impl_item {
-                    MethodImplItem(ref method) => method.span,
-                    TypeImplItem(ref typedef) => typedef.span,
-                }
-            }
+            Some(NodeTraitItem(trait_method)) => trait_method.span,
+            Some(NodeImplItem(ref impl_item)) => impl_item.span,
             Some(NodeVariant(variant)) => variant.span,
             Some(NodeExpr(expr)) => expr.span,
             Some(NodeStmt(stmt)) => stmt.span,
@@ -650,31 +603,8 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
 impl Named for Item { fn name(&self) -> Name { self.ident.name } }
 impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
 impl Named for Variant_ { fn name(&self) -> Name { self.name.name } }
-impl Named for TraitItem {
-    fn name(&self) -> Name {
-        match *self {
-            RequiredMethod(ref tm) => tm.ident.name,
-            ProvidedMethod(ref m) => m.name(),
-            TypeTraitItem(ref at) => at.ty_param.ident.name,
-        }
-    }
-}
-impl Named for ImplItem {
-    fn name(&self) -> Name {
-        match *self {
-            MethodImplItem(ref m) => m.name(),
-            TypeImplItem(ref td) => td.ident.name,
-        }
-    }
-}
-impl Named for Method {
-    fn name(&self) -> Name {
-        match self.node {
-            MethDecl(i, _, _, _, _, _, _, _) => i.name,
-            MethMac(_) => panic!("encountered unexpanded method macro."),
-        }
-    }
-}
+impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
+impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
 
 pub trait FoldOps {
     fn new_id(&self, id: NodeId) -> NodeId {
@@ -739,12 +669,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         self.parent = i.id;
         match i.node {
             ItemImpl(_, _, _, _, _, ref impl_items) => {
-                for impl_item in impl_items {
-                    let id = match **impl_item {
-                        MethodImplItem(ref m) => m.id,
-                        TypeImplItem(ref t) => t.id,
-                    };
-                    self.insert(id, NodeImplItem(impl_item));
+                for ii in impl_items {
+                    self.insert(ii.id, NodeImplItem(ii));
                 }
             }
             ItemEnum(ref enum_definition, _) => {
@@ -773,13 +699,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     }
                 }
 
-                for tm in trait_items {
-                    let id = match **tm {
-                        RequiredMethod(ref m) => m.id,
-                        ProvidedMethod(ref m) => m.id,
-                        TypeTraitItem(ref typ) => typ.ty_param.id,
-                    };
-                    self.insert(id, NodeTraitItem(tm));
+                for ti in trait_items {
+                    self.insert(ti.id, NodeTraitItem(ti));
                 }
             }
             _ => {}
@@ -788,6 +709,20 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         self.parent = parent;
     }
 
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        let parent = self.parent;
+        self.parent = ti.id;
+        visit::walk_trait_item(self, ti);
+        self.parent = parent;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        let parent = self.parent;
+        self.parent = ii.id;
+        visit::walk_impl_item(self, ii);
+        self.parent = parent;
+    }
+
     fn visit_pat(&mut self, pat: &'ast Pat) {
         self.insert(pat.id, match pat.node {
             // Note: this is at least *potentially* a pattern...
@@ -807,29 +742,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         visit::walk_stmt(self, stmt);
     }
 
-    fn visit_ty_method(&mut self, m: &'ast TypeMethod) {
-        let parent = self.parent;
-        self.parent = m.id;
-        self.visit_fn_decl(&*m.decl);
-        visit::walk_ty_method(self, m);
-        self.parent = parent;
-    }
-
     fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: &'ast Block, s: Span, id: NodeId) {
-        match fk {
-            visit::FkMethod(..) => {
-                let parent = self.parent;
-                self.parent = id;
-                self.visit_fn_decl(fd);
-                visit::walk_fn(self, fk, fd, b, s);
-                self.parent = parent;
-            }
-            _ => {
-                self.visit_fn_decl(fd);
-                visit::walk_fn(self, fk, fd, b, s);
-            }
-        }
+                b: &'ast Block, s: Span, _: NodeId) {
+        self.visit_fn_decl(fd);
+        visit::walk_fn(self, fk, fd, b, s);
     }
 
     fn visit_ty(&mut self, ty: &'ast Ty) {
@@ -911,33 +827,14 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
     let ii = match ii {
         IIItem(i) => IIItem(fld.fold_item(i).expect_one("expected one item")),
-        IITraitItem(d, ti) => match ti {
-            ProvidedMethod(m) => {
-                IITraitItem(fld.fold_ops.new_def_id(d),
-                            ProvidedMethod(fld.fold_method(m)
-                                              .expect_one("expected one method")))
-            }
-            RequiredMethod(ty_m) => {
-                IITraitItem(fld.fold_ops.new_def_id(d),
-                            RequiredMethod(fld.fold_type_method(ty_m)))
-            }
-            TypeTraitItem(at) => {
-                IITraitItem(
-                    fld.fold_ops.new_def_id(d),
-                    TypeTraitItem(fld.fold_associated_type(at)))
-            }
-        },
-        IIImplItem(d, m) => match m {
-            MethodImplItem(m) => {
-                IIImplItem(fld.fold_ops.new_def_id(d),
-                           MethodImplItem(fld.fold_method(m)
-                                             .expect_one("expected one method")))
-            }
-            TypeImplItem(t) => {
-                IIImplItem(fld.fold_ops.new_def_id(d),
-                           TypeImplItem(fld.fold_typedef(t)))
-            }
-        },
+        IITraitItem(d, ti) => {
+            IITraitItem(fld.fold_ops.new_def_id(d),
+                        fld.fold_trait_item(ti).expect_one("expected one trait item"))
+        }
+        IIImplItem(d, ii) => {
+            IIImplItem(fld.fold_ops.new_def_id(d),
+                       fld.fold_impl_item(ii).expect_one("expected one impl item"))
+        }
         IIForeign(i) => IIForeign(fld.fold_foreign_item(i))
     };
 
@@ -959,25 +856,14 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     // add it to the table now. Likewise with foreign items.
     match ii_parent.ii {
         IIItem(_) => {}
-        IITraitItem(_, ref trait_item) => {
-            let trait_item_id = match *trait_item {
-                ProvidedMethod(ref m) => m.id,
-                RequiredMethod(ref m) => m.id,
-                TypeTraitItem(ref ty) => ty.ty_param.id,
-            };
-
-            collector.insert(trait_item_id, NodeTraitItem(trait_item));
+        IITraitItem(_, ref ti) => {
+            collector.insert(ti.id, NodeTraitItem(ti));
         }
-        IIImplItem(_, ref impl_item) => {
-            let impl_item_id = match *impl_item {
-                MethodImplItem(ref m) => m.id,
-                TypeImplItem(ref ti) => ti.id,
-            };
-
-            collector.insert(impl_item_id, NodeImplItem(impl_item));
+        IIImplItem(_, ref ii) => {
+            collector.insert(ii.id, NodeImplItem(ii));
         }
         IIForeign(ref i) => {
-            collector.insert(i.id, NodeForeignItem(&**i));
+            collector.insert(i.id, NodeForeignItem(i));
         }
     }
     *map.map.borrow_mut() = collector.map;
@@ -993,8 +879,8 @@ impl<'a> NodePrinter for pprust::State<'a> {
         match *node {
             NodeItem(a)        => self.print_item(&*a),
             NodeForeignItem(a) => self.print_foreign_item(&*a),
-            NodeTraitItem(a)   => self.print_trait_method(&*a),
-            NodeImplItem(a)    => self.print_impl_item(&*a),
+            NodeTraitItem(a)   => self.print_trait_item(a),
+            NodeImplItem(a)    => self.print_impl_item(a),
             NodeVariant(a)     => self.print_variant(&*a),
             NodeExpr(a)        => self.print_expr(&*a),
             NodeStmt(a)        => self.print_stmt(&*a),
@@ -1041,48 +927,39 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             format!("foreign item {}{}", path_str, id_str)
         }
-        Some(NodeImplItem(ref ii)) => {
-            match **ii {
+        Some(NodeImplItem(ii)) => {
+            match ii.node {
                 MethodImplItem(ref m) => {
-                    match m.node {
-                        MethDecl(ident, _, _, _, _, _, _, _) =>
+                    match *m {
+                        MethDecl(..) =>
                             format!("method {} in {}{}",
-                                    token::get_ident(ident),
+                                    token::get_ident(ii.ident),
                                     map.path_to_string(id), id_str),
                         MethMac(ref mac) =>
                             format!("method macro {}{}",
                                     pprust::mac_to_string(mac), id_str)
                     }
                 }
-                TypeImplItem(ref t) => {
+                TypeImplItem(_) => {
                     format!("assoc type {} in {}{}",
-                            token::get_ident(t.ident),
+                            token::get_ident(ii.ident),
                             map.path_to_string(id),
                             id_str)
                 }
             }
         }
-        Some(NodeTraitItem(ref tm)) => {
-            match **tm {
-                RequiredMethod(ref m) => {
-                    format!("required method {} in {}{}",
-                            token::get_ident(m.ident),
-                            map.path_to_string(id),
-                            id_str)
-                }
-                ProvidedMethod(ref m) => {
-                    format!("provided method {} in {}{}",
-                            token::get_ident(m.pe_ident()),
-                            map.path_to_string(id),
-                            id_str)
-                }
-                TypeTraitItem(ref t) => {
-                    format!("assoc type {} in {}{}",
-                            token::get_ident(t.ty_param.ident),
-                            map.path_to_string(id),
-                            id_str)
-                }
-            }
+        Some(NodeTraitItem(ti)) => {
+            let kind = match ti.node {
+                RequiredMethod(_) => "required method",
+                ProvidedMethod(_) => "provided method",
+                TypeTraitItem(..) => "assoc type",
+            };
+
+            format!("{} {} in {}{}",
+                    kind,
+                    token::get_ident(ti.ident),
+                    map.path_to_string(id),
+                    id_str)
         }
         Some(NodeVariant(ref variant)) => {
             format!("variant {} in {}{}",
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index a8804b595d4..673ea4ac431 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -457,10 +457,12 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
         self.operation.visit_id(node_id);
 
         match function_kind {
-            visit::FkItemFn(_, generics, _, _) |
-            visit::FkMethod(_, generics, _) => {
+            visit::FkItemFn(_, generics, _, _) => {
                 self.visit_generics_helper(generics)
             }
+            visit::FkMethod(_, m) => {
+                self.visit_generics_helper(m.pe_generics())
+            }
             visit::FkFnBlock => {}
         }
 
@@ -496,13 +498,14 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
         visit::walk_struct_def(self, struct_def);
     }
 
-    fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
-        match *tm {
-            ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
-            ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
-            ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id),
-        }
-        visit::walk_trait_item(self, tm);
+    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+        self.operation.visit_id(ti.id);
+        visit::walk_trait_item(self, ti);
+    }
+
+    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+        self.operation.visit_id(ii.id);
+        visit::walk_impl_item(self, ii);
     }
 
     fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
@@ -650,20 +653,18 @@ pub fn lit_is_str(lit: &Lit) -> bool {
 /// not a macro invocation. This check is guaranteed to succeed, assuming
 /// that the invocations are indeed gone.
 pub trait PostExpansionMethod {
-    fn pe_ident(&self) -> ast::Ident;
     fn pe_generics<'a>(&'a self) -> &'a ast::Generics;
     fn pe_abi(&self) -> Abi;
     fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf;
     fn pe_unsafety(&self) -> ast::Unsafety;
     fn pe_fn_decl<'a>(&'a self) -> &'a ast::FnDecl;
     fn pe_body<'a>(&'a self) -> &'a ast::Block;
-    fn pe_vis(&self) -> ast::Visibility;
 }
 
 macro_rules! mf_method{
     ($meth_name:ident, $field_ty:ty, $field_pat:pat, $result:expr) => {
         fn $meth_name<'a>(&'a self) -> $field_ty {
-            match self.node {
+            match *self {
                 $field_pat => $result,
                 MethMac(_) => {
                     panic!("expected an AST without macro invocations");
@@ -675,20 +676,18 @@ macro_rules! mf_method{
 
 
 impl PostExpansionMethod for Method {
-    mf_method! { pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident }
     mf_method! {
         pe_generics,&'a ast::Generics,
-        MethDecl(_,ref generics,_,_,_,_,_,_),generics
+        MethDecl(ref generics,_,_,_,_,_),generics
     }
-    mf_method! { pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi }
+    mf_method! { pe_abi,Abi,MethDecl(_,abi,_,_,_,_),abi }
     mf_method! {
         pe_explicit_self,&'a ast::ExplicitSelf,
-        MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self
+        MethDecl(_,_,ref explicit_self,_,_,_),explicit_self
     }
-    mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety }
-    mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl }
-    mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body }
-    mf_method! { pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis }
+    mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,unsafety,_,_),unsafety }
+    mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,ref decl,_),&**decl }
+    mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,ref body),&**body }
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index dfe3477bddc..489a7721d7b 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -118,13 +118,13 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
     let item = match item {
         ast::ItemImpl(u, o, a, b, c, impl_items) => {
             let impl_items = impl_items.into_iter()
-                                       .filter(|ii| impl_item_in_cfg(cx, ii))
+                                       .filter(|ii| (cx.in_cfg)(&ii.attrs))
                                        .collect();
             ast::ItemImpl(u, o, a, b, c, impl_items)
         }
         ast::ItemTrait(u, a, b, methods) => {
             let methods = methods.into_iter()
-                                 .filter(|m| trait_method_in_cfg(cx, m))
+                                 .filter(|ti| (cx.in_cfg)(&ti.attrs))
                                  .collect();
             ast::ItemTrait(u, a, b, methods)
         }
@@ -246,25 +246,6 @@ fn foreign_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ForeignItem) -> bool
     return (cx.in_cfg)(&item.attrs);
 }
 
-fn trait_method_in_cfg<F>(cx: &mut Context<F>, meth: &ast::TraitItem) -> bool where
-    F: FnMut(&[ast::Attribute]) -> bool
-{
-    match *meth {
-        ast::RequiredMethod(ref meth) => (cx.in_cfg)(&meth.attrs),
-        ast::ProvidedMethod(ref meth) => (cx.in_cfg)(&meth.attrs),
-        ast::TypeTraitItem(ref typ) => (cx.in_cfg)(&typ.attrs),
-    }
-}
-
-fn impl_item_in_cfg<F>(cx: &mut Context<F>, impl_item: &ast::ImplItem) -> bool where
-    F: FnMut(&[ast::Attribute]) -> bool
-{
-    match *impl_item {
-        ast::MethodImplItem(ref meth) => (cx.in_cfg)(&meth.attrs),
-        ast::TypeImplItem(ref typ) => (cx.in_cfg)(&typ.attrs),
-    }
-}
-
 // Determine if an item should be translated in the current crate
 // configuration based on the item's attributes
 fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b999680ff1a..cad5f97a4a5 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -77,23 +77,16 @@ impl<F> ItemModifier for F
 #[derive(Debug,Clone)]
 pub enum Annotatable {
     Item(P<ast::Item>),
-    TraitItem(ast::TraitItem),
-    ImplItem(ast::ImplItem),
+    TraitItem(P<ast::TraitItem>),
+    ImplItem(P<ast::ImplItem>),
 }
 
 impl Annotatable {
     pub fn attrs(&self) -> &[ast::Attribute] {
         match *self {
             Annotatable::Item(ref i) => &i.attrs,
-            Annotatable::TraitItem(ref i) => match *i {
-                ast::RequiredMethod(ref tm) => &tm.attrs,
-                ast::ProvidedMethod(ref m) => &m.attrs,
-                ast::TypeTraitItem(ref at) => &at.attrs,
-            },
-            Annotatable::ImplItem(ref i) => match *i {
-                ast::MethodImplItem(ref m) => &m.attrs,
-                ast::TypeImplItem(ref t) => &t.attrs,
-            }
+            Annotatable::TraitItem(ref ti) => &ti.attrs,
+            Annotatable::ImplItem(ref ii) => &ii.attrs,
         }
     }
 
@@ -103,20 +96,12 @@ impl Annotatable {
                 attrs: attrs,
                 ..i
             })),
-            Annotatable::TraitItem(i) => Annotatable::TraitItem(match i {
-                ast::RequiredMethod(tm) =>
-                    ast::RequiredMethod(ast::TypeMethod { attrs: attrs, ..tm }),
-                ast::ProvidedMethod(m) =>
-                    ast::ProvidedMethod(ast::Method { attrs: attrs, ..m }),
-                ast::TypeTraitItem(at) =>
-                    ast::TypeTraitItem(ast::AssociatedType { attrs: attrs, ..at }),
-            }),
-            Annotatable::ImplItem(i) => Annotatable::ImplItem(match i {
-                ast::MethodImplItem(m) =>
-                    ast::MethodImplItem(ast::Method { attrs: attrs, ..m }),
-                ast::TypeImplItem(t) =>
-                    ast::TypeImplItem(ast::Typedef { attrs: attrs, ..t }),
-            })
+            Annotatable::TraitItem(i) => Annotatable::TraitItem(i.map(|ti| {
+                ast::TraitItem { attrs: attrs, ..ti }
+            })),
+            Annotatable::ImplItem(i) => Annotatable::ImplItem(i.map(|ii| {
+                ast::ImplItem { attrs: attrs, ..ii }
+            })),
         }
     }
 
@@ -127,14 +112,14 @@ impl Annotatable {
         }
     }
 
-    pub fn expect_trait_item(self) -> ast::TraitItem {
+    pub fn expect_trait_item(self) -> P<ast::TraitItem> {
         match self {
             Annotatable::TraitItem(i) => i,
             _ => panic!("expected Item")
         }
     }
 
-    pub fn expect_impl_item(self) -> ast::ImplItem {
+    pub fn expect_impl_item(self) -> P<ast::ImplItem> {
         match self {
             Annotatable::ImplItem(i) => i,
             _ => panic!("expected Item")
@@ -244,7 +229,7 @@ pub trait MacResult {
     }
 
     /// Create zero or more methods.
-    fn make_methods(self: Box<Self>) -> Option<SmallVector<ast::Method>> {
+    fn make_methods(self: Box<Self>) -> Option<SmallVector<P<ast::ImplItem>>> {
         None
     }
 
@@ -290,7 +275,7 @@ make_MacEager! {
     expr: P<ast::Expr>,
     pat: P<ast::Pat>,
     items: SmallVector<P<ast::Item>>,
-    methods: SmallVector<ast::Method>,
+    methods: SmallVector<P<ast::ImplItem>>,
     stmt: P<ast::Stmt>,
 }
 
@@ -303,7 +288,7 @@ impl MacResult for MacEager {
         self.items
     }
 
-    fn make_methods(self: Box<Self>) -> Option<SmallVector<ast::Method>> {
+    fn make_methods(self: Box<Self>) -> Option<SmallVector<P<ast::ImplItem>>> {
         self.methods
     }
 
@@ -392,7 +377,7 @@ impl MacResult for DummyResult {
             Some(SmallVector::zero())
         }
     }
-    fn make_methods(self: Box<DummyResult>) -> Option<SmallVector<ast::Method>> {
+    fn make_methods(self: Box<DummyResult>) -> Option<SmallVector<P<ast::ImplItem>>> {
         if self.expr_only {
             None
         } else {
@@ -500,9 +485,6 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
         syntax_expanders.insert(intern("quote_ty"),
                            builtin_normal_expander(
                                 ext::quote::expand_quote_ty));
-        syntax_expanders.insert(intern("quote_method"),
-                           builtin_normal_expander(
-                                ext::quote::expand_quote_method));
         syntax_expanders.insert(intern("quote_item"),
                            builtin_normal_expander(
                                 ext::quote::expand_quote_item));
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 0573289150c..a4962afff3c 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -386,23 +386,23 @@ impl<'a> TraitDef<'a> {
                            cx: &mut ExtCtxt,
                            type_ident: Ident,
                            generics: &Generics,
-                           methods: Vec<ast::Method>) -> P<ast::Item> {
+                           methods: Vec<P<ast::ImplItem>>) -> P<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
-        // Transform associated types from `deriving::ty::Ty` into `ast::Typedef`
+        // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
         let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
-            ast::Typedef {
+            P(ast::ImplItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 ident: ident,
                 vis: ast::Inherited,
                 attrs: Vec::new(),
-                typ: type_def.to_ty(cx,
+                node: ast::TypeImplItem(type_def.to_ty(cx,
                     self.span,
                     type_ident,
                     generics
-                ),
-            }
+                )),
+            })
         });
 
         let Generics { mut lifetimes, ty_params, mut where_clause } =
@@ -510,14 +510,7 @@ impl<'a> TraitDef<'a> {
                           trait_generics,
                           opt_trait_ref,
                           self_type,
-                          methods.into_iter()
-                                 .map(|method| {
-                                     ast::MethodImplItem(method)
-                                 }).chain(
-                                     associated_types.map(|type_| {
-                                         ast::TypeImplItem(type_)
-                                     })
-                                 ).map(P).collect()))
+                          methods.into_iter().chain(associated_types).collect()))
     }
 
     fn expand_struct_def(&self,
@@ -702,7 +695,7 @@ impl<'a> MethodDef<'a> {
                      abi: Abi,
                      explicit_self: ast::ExplicitSelf,
                      arg_types: Vec<(Ident, P<ast::Ty>)> ,
-                     body: P<Expr>) -> ast::Method {
+                     body: P<Expr>) -> P<ast::ImplItem> {
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
@@ -725,19 +718,20 @@ impl<'a> MethodDef<'a> {
         let body_block = cx.block_expr(body);
 
         // Create the method.
-        ast::Method {
-            attrs: self.attributes.clone(),
+        P(ast::ImplItem {
             id: ast::DUMMY_NODE_ID,
+            attrs: self.attributes.clone(),
             span: trait_.span,
-            node: ast::MethDecl(method_ident,
-                                fn_generics,
-                                abi,
-                                explicit_self,
-                                ast::Unsafety::Normal,
-                                fn_decl,
-                                body_block,
-                                ast::Inherited)
-        }
+            vis: ast::Inherited,
+            ident: method_ident,
+            node: ast::MethodImplItem(
+                ast::MethDecl(fn_generics,
+                              abi,
+                              explicit_self,
+                              ast::Unsafety::Normal,
+                              fn_decl,
+                              body_block))
+        })
     }
 
     /// ```
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 96859b94f1d..5fb0126cdd0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -25,6 +25,7 @@ use ext::base::*;
 use feature_gate::{self, Features};
 use fold;
 use fold::*;
+use owned_slice::OwnedSlice;
 use parse;
 use parse::token::{fresh_mark, fresh_name, intern};
 use parse::token;
@@ -1174,29 +1175,42 @@ fn expand_annotatable(a: Annotatable,
                 noop_fold_item(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
             }
         },
-        Annotatable::TraitItem(it) => match it {
-            ast::TraitItem::ProvidedMethod(m) => {
-                expand_method(m, fld).into_iter().map(|m|
-                    Annotatable::TraitItem(ast::TraitItem::ProvidedMethod(m))).collect()
-            }
-            ast::TraitItem::RequiredMethod(m) => {
-                SmallVector::one(Annotatable::TraitItem(
-                    ast::TraitItem::RequiredMethod(fld.fold_type_method(m))))
+        Annotatable::TraitItem(it) => match it.node {
+            ast::ProvidedMethod(ast::MethMac(_)) => {
+                // HACK(eddyb): Expand method macros in a trait as if they were in an impl.
+                let ii = it.and_then(|ti| match ti.node {
+                    ast::ProvidedMethod(m) => P(ast::ImplItem {
+                        id: ti.id,
+                        ident: ti.ident,
+                        attrs: ti.attrs,
+                        vis: ast::Inherited,
+                        node: ast::MethodImplItem(m),
+                        span: ti.span
+                    }),
+                    _ => unreachable!()
+                });
+                expand_method(ii, fld).into_iter().map(|ii| {
+                    Annotatable::TraitItem(ii.and_then(|ii| P(ast::TraitItem {
+                        id: ii.id,
+                        ident: ii.ident,
+                        attrs: ii.attrs,
+                        node: match ii.node {
+                            ast::MethodImplItem(m) => ast::ProvidedMethod(m),
+                            ast::TypeImplItem(ty) => {
+                                ast::TypeTraitItem(OwnedSlice::empty(), Some(ty))
+                            }
+                        },
+                        span: ii.span
+                    })))
+                }).collect()
             }
-            ast::TraitItem::TypeTraitItem(t) => {
-                SmallVector::one(Annotatable::TraitItem(
-                    ast::TraitItem::TypeTraitItem(fld.fold_associated_type(t))))
+            _ => {
+                fold::noop_fold_trait_item(it, fld).into_iter()
+                    .map(|ti| Annotatable::TraitItem(ti)).collect()
             }
         },
-        Annotatable::ImplItem(it) => match it {
-            ast::ImplItem::MethodImplItem(m) => {
-                expand_method(m, fld).into_iter().map(|m|
-                    Annotatable::ImplItem(ast::ImplItem::MethodImplItem(m))).collect()
-            }
-            ast::ImplItem::TypeImplItem(t) => {
-                SmallVector::one(Annotatable::ImplItem(
-                    ast::ImplItem::TypeImplItem(fld.fold_typedef(t))))
-            }
+        Annotatable::ImplItem(ii) => {
+            expand_method(ii, fld).into_iter().map(Annotatable::ImplItem).collect()
         }
     };
 
@@ -1204,21 +1218,6 @@ fn expand_annotatable(a: Annotatable,
     new_items
 }
 
-fn expand_trait_item(i: ast::TraitItem,
-                     fld: &mut MacroExpander)
-                     -> SmallVector<ast::TraitItem> {
-    expand_annotatable(Annotatable::TraitItem(i), fld)
-        .into_iter().map(|i| i.expect_trait_item()).collect()
-
-}
-
-fn expand_impl_item(i: ast::ImplItem,
-                    fld: &mut MacroExpander)
-                    -> SmallVector<ast::ImplItem> {
-    expand_annotatable(Annotatable::ImplItem(i), fld)
-        .into_iter().map(|i| i.expect_impl_item()).collect()
-}
-
 // partition the attributes into ItemModifiers and others
 fn modifiers(attrs: &Vec<ast::Attribute>,
              fld: &MacroExpander)
@@ -1292,37 +1291,18 @@ fn expand_item_multi_modifier(mut it: Annotatable,
     expand_item_multi_modifier(it, fld)
 }
 
-// expand a method
-fn expand_method(m: ast::Method, fld: &mut MacroExpander) -> SmallVector<ast::Method> {
-    match m.node {
-        ast::MethDecl(ident,
-                      generics,
-                      abi,
-                      explicit_self,
-                      fn_style,
-                      decl,
-                      body,
-                      vis) => {
-            let id = fld.new_id(m.id);
-            let (rewritten_fn_decl, rewritten_body)
-                = expand_and_rename_fn_decl_and_block(decl, body, fld);
-            SmallVector::one(ast::Method {
-                    attrs: fold::fold_attrs(m.attrs, fld),
-                    id: id,
-                    span: fld.new_span(m.span),
-                    node: ast::MethDecl(fld.fold_ident(ident),
-                                        noop_fold_generics(generics, fld),
-                                        abi,
-                                        fld.fold_explicit_self(explicit_self),
-                                        fn_style,
-                                        rewritten_fn_decl,
-                                        rewritten_body,
-                                        vis)
-                })
-        },
-        ast::MethMac(mac) => {
+// expand an impl item if it's a method macro
+fn expand_method(ii: P<ast::ImplItem>, fld: &mut MacroExpander)
+                 -> SmallVector<P<ast::ImplItem>> {
+    let ii = fold::noop_fold_impl_item(ii, fld).expect_one("expected one impl item");
+    match ii.node {
+        ast::MethodImplItem(ast::MethMac(_)) => {
+            let (span, mac) = ii.and_then(|ii| match ii.node {
+                ast::MethodImplItem(ast::MethMac(mac)) => (ii.span, mac),
+                _ => unreachable!()
+            });
             let maybe_new_methods =
-                expand_mac_invoc(mac, m.span,
+                expand_mac_invoc(mac, span,
                                  |r| r.make_methods(),
                                  |meths, mark| meths.move_map(|m| mark_method(m, mark)),
                                  fld);
@@ -1331,7 +1311,7 @@ fn expand_method(m: ast::Method, fld: &mut MacroExpander) -> SmallVector<ast::Me
                 Some(methods) => {
                     // expand again if necessary
                     let new_methods = methods.into_iter()
-                                             .flat_map(|m| fld.fold_method(m).into_iter())
+                                             .flat_map(|m| expand_method(m, fld).into_iter())
                                              .collect();
                     fld.cx.bt_pop();
                     new_methods
@@ -1339,6 +1319,7 @@ fn expand_method(m: ast::Method, fld: &mut MacroExpander) -> SmallVector<ast::Me
                 None => SmallVector::zero()
             }
         }
+        _ => SmallVector::one(ii)
     }
 }
 
@@ -1410,16 +1391,30 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
         expand_arm(arm, self)
     }
 
-    fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
-        expand_trait_item(i, self)
+    fn fold_method(&mut self, m: ast::Method) -> ast::Method {
+        match m {
+            ast::MethDecl(generics, abi, explicit_self, fn_style, decl, body) => {
+                let (rewritten_fn_decl, rewritten_body)
+                    = expand_and_rename_fn_decl_and_block(decl, body, self);
+                ast::MethDecl(self.fold_generics(generics),
+                              abi,
+                              self.fold_explicit_self(explicit_self),
+                              fn_style,
+                              rewritten_fn_decl,
+                              rewritten_body)
+            }
+            ast::MethMac(mac) => ast::MethMac(mac)
+        }
     }
 
-    fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
-        expand_impl_item(i, self)
+    fn fold_trait_item(&mut self, i: P<ast::TraitItem>) -> SmallVector<P<ast::TraitItem>> {
+        expand_annotatable(Annotatable::TraitItem(i), self)
+            .into_iter().map(|i| i.expect_trait_item()).collect()
     }
 
-    fn fold_method(&mut self, method: ast::Method) -> SmallVector<ast::Method> {
-        expand_method(method, self)
+    fn fold_impl_item(&mut self, i: P<ast::ImplItem>) -> SmallVector<P<ast::ImplItem>> {
+        expand_annotatable(Annotatable::ImplItem(i), self)
+            .into_iter().map(|i| i.expect_impl_item()).collect()
     }
 
     fn fold_ty(&mut self, t: P<ast::Ty>) -> P<ast::Ty> {
@@ -1565,9 +1560,9 @@ fn mark_item(expr: P<ast::Item>, m: Mrk) -> P<ast::Item> {
 }
 
 // apply a given mark to the given item. Used following the expansion of a macro.
-fn mark_method(expr: ast::Method, m: Mrk) -> ast::Method {
-    Marker{mark:m}.fold_method(expr)
-        .expect_one("marking an item didn't return exactly one method")
+fn mark_method(ii: P<ast::ImplItem>, m: Mrk) -> P<ast::ImplItem> {
+    Marker{mark:m}.fold_impl_item(ii)
+        .expect_one("marking an impl item didn't return exactly one method")
 }
 
 /// Check that there are no macro invocations left in the AST:
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 737648cd90c..48c045ee4f9 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -176,7 +176,6 @@ pub mod rt {
     impl_to_source! { ast::Arg, arg_to_string }
     impl_to_source! { Generics, generics_to_string }
     impl_to_source! { P<ast::Item>, item_to_string }
-    impl_to_source! { P<ast::Method>, method_to_string }
     impl_to_source! { P<ast::Stmt>, stmt_to_string }
     impl_to_source! { P<ast::Expr>, expr_to_string }
     impl_to_source! { P<ast::Pat>, pat_to_string }
@@ -311,7 +310,6 @@ pub mod rt {
     impl_to_tokens! { P<ast::Item> }
     impl_to_tokens! { P<ast::Pat> }
     impl_to_tokens! { ast::Arm }
-    impl_to_tokens! { P<ast::Method> }
     impl_to_tokens_lifetime! { &'a [P<ast::Item>] }
     impl_to_tokens! { ast::Ty }
     impl_to_tokens_lifetime! { &'a [ast::Ty] }
@@ -446,15 +444,6 @@ pub fn expand_quote_ty(cx: &mut ExtCtxt,
     base::MacEager::expr(expanded)
 }
 
-pub fn expand_quote_method(cx: &mut ExtCtxt,
-                           sp: Span,
-                           tts: &[ast::TokenTree])
-                           -> Box<base::MacResult+'static> {
-    let expanded = expand_parse_call(cx, sp, "parse_method_with_outer_attributes",
-                                     vec!(), tts);
-    base::MacEager::expr(expanded)
-}
-
 pub fn expand_quote_stmt(cx: &mut ExtCtxt,
                          sp: Span,
                          tts: &[ast::TokenTree])
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index dcdfad4632d..dad50af9a91 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -82,7 +82,8 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
         Some(ret)
     }
 
-    fn make_methods(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<ast::Method>> {
+    fn make_methods(self: Box<ParserAnyMacro<'a>>)
+                    -> Option<SmallVector<P<ast::ImplItem>>> {
         let mut ret = SmallVector::zero();
         loop {
             let mut parser = self.parser.borrow_mut();
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5109a19fdb6..d99f1600cb3 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -110,11 +110,7 @@ pub trait Folder : Sized {
         noop_fold_fn_decl(d, self)
     }
 
-    fn fold_type_method(&mut self, m: TypeMethod) -> TypeMethod {
-        noop_fold_type_method(m, self)
-    }
-
-    fn fold_method(&mut self, m: Method) -> SmallVector<Method> {
+    fn fold_method(&mut self, m: Method) -> Method {
         noop_fold_method(m, self)
     }
 
@@ -315,15 +311,6 @@ pub trait Folder : Sized {
         noop_fold_where_predicate(where_predicate, self)
     }
 
-    fn fold_typedef(&mut self, typedef: Typedef) -> Typedef {
-        noop_fold_typedef(typedef, self)
-    }
-
-    fn fold_associated_type(&mut self, associated_type: AssociatedType)
-                            -> AssociatedType {
-        noop_fold_associated_type(associated_type, self)
-    }
-
     fn new_id(&mut self, i: NodeId) -> NodeId {
         i
     }
@@ -829,41 +816,6 @@ pub fn noop_fold_where_predicate<T: Folder>(
     }
 }
 
-pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
-                            -> Typedef
-                            where T: Folder {
-    let new_id = folder.new_id(t.id);
-    let new_span = folder.new_span(t.span);
-    let new_attrs = t.attrs.iter().flat_map(|attr| {
-        folder.fold_attribute((*attr).clone()).into_iter()
-    }).collect();
-    let new_ident = folder.fold_ident(t.ident);
-    let new_type = folder.fold_ty(t.typ);
-    ast::Typedef {
-        ident: new_ident,
-        typ: new_type,
-        id: new_id,
-        span: new_span,
-        vis: t.vis,
-        attrs: new_attrs,
-    }
-}
-
-pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
-                                    -> AssociatedType
-                                    where T: Folder
-{
-    let new_attrs = at.attrs
-                      .iter()
-                      .flat_map(|attr| folder.fold_attribute((*attr).clone()).into_iter())
-                      .collect();
-    let new_param = folder.fold_ty_param(at.ty_param);
-    ast::AssociatedType {
-        attrs: new_attrs,
-        ty_param: new_param,
-    }
-}
-
 pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
     struct_def.map(|StructDef { fields, ctor_id }| StructDef {
         fields: fields.move_map(|f| fld.fold_struct_field(f)),
@@ -1020,55 +972,43 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
 
 pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T)
                                        -> SmallVector<P<TraitItem>> {
-    i.map(|i| SmallVector::one(P(match i {
-        RequiredMethod(m) => RequiredMethod(folder.fold_type_method(m)),
-        ProvidedMethod(method) => {
-            return folder.fold_method(method).into_iter()
-                         .map(|m| P(ProvidedMethod(m))).collect();
-        }
-        TypeTraitItem(at) => {
-            TypeTraitItem(folder.fold_associated_type(at))
-        }
-    })))
+    SmallVector::one(i.map(|TraitItem {id, ident, attrs, node, span}| TraitItem {
+        id: folder.new_id(id),
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
+        node: match node {
+            RequiredMethod(TypeMethod { unsafety, abi, decl, generics, explicit_self }) => {
+                RequiredMethod(TypeMethod {
+                    unsafety: unsafety,
+                    abi: abi,
+                    decl: folder.fold_fn_decl(decl),
+                    generics: folder.fold_generics(generics),
+                    explicit_self: folder.fold_explicit_self(explicit_self)
+                })
+            }
+            ProvidedMethod(m) => ProvidedMethod(folder.fold_method(m)),
+            TypeTraitItem(bounds, default) => {
+                TypeTraitItem(folder.fold_bounds(bounds),
+                              default.map(|x| folder.fold_ty(x)))
+            }
+        },
+        span: folder.new_span(span)
+    }))
 }
 
 pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
                                       -> SmallVector<P<ImplItem>> {
-    i.and_then(|i| match i {
-        MethodImplItem(x) => {
-            folder.fold_method(x).into_iter().map(|m| P(MethodImplItem(m))).collect()
-        }
-        TypeImplItem(t) => {
-            SmallVector::one(TypeImplItem(folder.fold_typedef(t)))
-        }
-    })
-}
-
-pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
-    let TypeMethod {
-        id,
-        ident,
-        attrs,
-        unsafety,
-        abi,
-        decl,
-        generics,
-        explicit_self,
-        vis,
-        span
-    } = m;
-    TypeMethod {
-        id: fld.new_id(id),
-        ident: fld.fold_ident(ident),
-        attrs: fold_attrs(attrs, fld),
-        unsafety: unsafety,
-        abi: abi,
-        decl: fld.fold_fn_decl(decl),
-        generics: fld.fold_generics(generics),
-        explicit_self: fld.fold_explicit_self(explicit_self),
+    SmallVector::one(i.map(|ImplItem {id, ident, attrs, node, vis, span}| ImplItem {
+        id: folder.new_id(id),
+        ident: folder.fold_ident(ident),
+        attrs: fold_attrs(attrs, folder),
         vis: vis,
-        span: fld.new_span(span)
-    }
+        node: match node  {
+            MethodImplItem(m) => MethodImplItem(folder.fold_method(m)),
+            TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty))
+        },
+        span: folder.new_span(span)
+    }))
 }
 
 pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
@@ -1168,34 +1108,23 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
 }
 
 // Default fold over a method.
-// Invariant: produces exactly one method.
-pub fn noop_fold_method<T: Folder>(Method {id, attrs, node, span}: Method, folder: &mut T)
-                                   -> SmallVector<Method> {
-    SmallVector::one(Method {
-        id: folder.new_id(id),
-        attrs: fold_attrs(attrs, folder),
-        node: match node {
-            MethDecl(ident,
-                     generics,
+pub fn noop_fold_method<T: Folder>(method: Method, folder: &mut T) -> Method {
+    match method {
+        MethDecl(generics,
+                 abi,
+                 explicit_self,
+                 unsafety,
+                 decl,
+                 body) => {
+            MethDecl(folder.fold_generics(generics),
                      abi,
-                     explicit_self,
+                     folder.fold_explicit_self(explicit_self),
                      unsafety,
-                     decl,
-                     body,
-                     vis) => {
-                MethDecl(folder.fold_ident(ident),
-                         folder.fold_generics(generics),
-                         abi,
-                         folder.fold_explicit_self(explicit_self),
-                         unsafety,
-                         folder.fold_fn_decl(decl),
-                         folder.fold_block(body),
-                         vis)
-            },
-            MethMac(mac) => MethMac(folder.fold_mac(mac)),
+                     folder.fold_fn_decl(decl),
+                     folder.fold_block(body))
         },
-        span: folder.new_span(span)
-    })
+        MethMac(mac) => MethMac(folder.fold_mac(mac))
+    }
 }
 
 pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 63c0f4e1cfa..a38508d2cf5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -11,7 +11,7 @@
 pub use self::PathParsingMode::*;
 
 use abi;
-use ast::{AssociatedType, BareFnTy};
+use ast::{BareFnTy};
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
@@ -38,7 +38,7 @@ use ast::{LitBool, LitChar, LitByte, LitBinary};
 use ast::{LitStr, LitInt, Local, LocalLet};
 use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces};
 use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource};
-use ast::{Method, MutTy, BiMul, Mutability};
+use ast::{MutTy, BiMul, Mutability};
 use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot};
 use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
@@ -55,7 +55,7 @@ use ast::{TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
-use ast::{TypeImplItem, TypeTraitItem, Typedef,};
+use ast::{TypeImplItem, TypeTraitItem};
 use ast::{UnnamedField, UnsafeBlock};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
@@ -1275,35 +1275,37 @@ impl<'a> Parser<'a> {
 
     /// Parses `type Foo;` in a trait declaration only. The `type` keyword has
     /// already been parsed.
-    fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
-                             -> AssociatedType
-    {
-        let ty_param = self.parse_ty_param();
+    fn parse_assoc_ty_in_trait(&mut self, attrs: Vec<Attribute>)
+                               -> P<TraitItem> {
+        let TyParam {id, ident, bounds, default, span} = self.parse_ty_param();
         self.expect(&token::Semi);
-        AssociatedType {
+        P(TraitItem {
+            id: id,
+            ident: ident,
             attrs: attrs,
-            ty_param: ty_param,
-        }
+            node: TypeTraitItem(bounds, default),
+            span: span,
+        })
     }
 
     /// Parses `type Foo = TYPE;` in an implementation declaration only. The
     /// `type` keyword has already been parsed.
-    fn parse_typedef(&mut self, attrs: Vec<Attribute>, vis: Visibility)
-                     -> Typedef {
+    fn parse_assoc_ty_in_impl(&mut self, attrs: Vec<Attribute>, vis: Visibility)
+                              -> P<ImplItem> {
         let lo = self.span.lo;
         let ident = self.parse_ident();
         self.expect(&token::Eq);
         let typ = self.parse_ty_sum();
         let hi = self.span.hi;
         self.expect(&token::Semi);
-        Typedef {
+        P(ImplItem {
             id: ast::DUMMY_NODE_ID,
             span: mk_sp(lo, hi),
             ident: ident,
             vis: vis,
             attrs: attrs,
-            typ: typ,
-        }
+            node: TypeImplItem(typ),
+        })
     }
 
     /// Parse the items in a trait declaration
@@ -1313,14 +1315,13 @@ impl<'a> Parser<'a> {
             &token::CloseDelim(token::Brace),
             seq_sep_none(),
             |p| {
-            let attrs = p.parse_outer_attributes();
+            let mut attrs = p.parse_outer_attributes();
 
             if p.eat_keyword(keywords::Type) {
-                P(TypeTraitItem(p.parse_associated_type(attrs)))
+                p.parse_assoc_ty_in_trait(attrs)
             } else {
                 let lo = p.span.lo;
 
-                let vis = p.parse_visibility();
                 let style = p.parse_unsafety();
                 let abi = if p.eat_keyword(keywords::Extern) {
                     p.parse_opt_abi().unwrap_or(abi::C)
@@ -1342,42 +1343,29 @@ impl<'a> Parser<'a> {
                 p.parse_where_clause(&mut generics);
 
                 let hi = p.last_span.hi;
-                match p.token {
+                let node = match p.token {
                   token::Semi => {
                     p.bump();
                     debug!("parse_trait_methods(): parsing required method");
-                    P(RequiredMethod(TypeMethod {
-                        ident: ident,
-                        attrs: attrs,
+                    RequiredMethod(TypeMethod {
                         unsafety: style,
                         decl: d,
                         generics: generics,
                         abi: abi,
                         explicit_self: explicit_self,
-                        id: ast::DUMMY_NODE_ID,
-                        span: mk_sp(lo, hi),
-                        vis: vis,
-                    }))
+                    })
                   }
                   token::OpenDelim(token::Brace) => {
                     debug!("parse_trait_methods(): parsing provided method");
                     let (inner_attrs, body) =
                         p.parse_inner_attrs_and_block();
-                    let mut attrs = attrs;
                     attrs.push_all(&inner_attrs[..]);
-                    P(ProvidedMethod(ast::Method {
-                        attrs: attrs,
-                        id: ast::DUMMY_NODE_ID,
-                        span: mk_sp(lo, hi),
-                        node: ast::MethDecl(ident,
-                                            generics,
-                                            abi,
-                                            explicit_self,
-                                            style,
-                                            d,
-                                            body,
-                                            vis)
-                    }))
+                    ProvidedMethod(ast::MethDecl(generics,
+                                                 abi,
+                                                 explicit_self,
+                                                 style,
+                                                 d,
+                                                 body))
                   }
 
                   _ => {
@@ -1385,7 +1373,15 @@ impl<'a> Parser<'a> {
                       p.fatal(&format!("expected `;` or `{{`, found `{}`",
                                        token_str)[..])
                   }
-                }
+                };
+
+                P(TraitItem {
+                    id: ast::DUMMY_NODE_ID,
+                    ident: ident,
+                    attrs: attrs,
+                    node: node,
+                    span: mk_sp(lo, hi),
+                })
             }
         })
     }
@@ -4692,7 +4688,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a method in a trait impl
-    pub fn parse_method_with_outer_attributes(&mut self) -> Method {
+    pub fn parse_method_with_outer_attributes(&mut self) -> P<ImplItem> {
         let attrs = self.parse_outer_attributes();
         let visa = self.parse_visibility();
         self.parse_method(attrs, visa)
@@ -4712,12 +4708,12 @@ impl<'a> Parser<'a> {
     /// Parse a method in a trait impl, starting with `attrs` attributes.
     pub fn parse_method(&mut self,
                         attrs: Vec<Attribute>,
-                        visa: Visibility)
-                        -> Method {
+                        vis: Visibility)
+                        -> P<ImplItem> {
         let lo = self.span.lo;
 
         // code copied from parse_macro_use_or_failure... abstraction!
-        let (method_, hi, new_attrs) = {
+        let (method_, hi, new_attrs, ident) = {
             if !self.token.is_any_keyword()
                 && self.look_ahead(1, |t| *t == token::Not)
                 && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
@@ -4725,7 +4721,7 @@ impl<'a> Parser<'a> {
                 // method macro.
 
                 let last_span = self.last_span;
-                self.complain_if_pub_macro(visa, last_span);
+                self.complain_if_pub_macro(vis, last_span);
 
                 let pth = self.parse_path(NoTypesAllowed);
                 self.expect(&token::Not);
@@ -4742,7 +4738,8 @@ impl<'a> Parser<'a> {
                 if delim != token::Brace {
                     self.expect(&token::Semi)
                 }
-                (ast::MethMac(m), self.span.hi, attrs)
+                (ast::MethMac(m), self.span.hi, attrs,
+                 token::special_idents::invalid)
             } else {
                 let unsafety = self.parse_unsafety();
                 let abi = if self.eat_keyword(keywords::Extern) {
@@ -4761,23 +4758,23 @@ impl<'a> Parser<'a> {
                 let body_span = body.span;
                 let mut new_attrs = attrs;
                 new_attrs.push_all(&inner_attrs[..]);
-                (ast::MethDecl(ident,
-                               generics,
+                (ast::MethDecl(generics,
                                abi,
                                explicit_self,
                                unsafety,
                                decl,
-                               body,
-                               visa),
-                 body_span.hi, new_attrs)
+                               body),
+                 body_span.hi, new_attrs, ident)
             }
         };
-        ast::Method {
-            attrs: new_attrs,
+        P(ImplItem {
             id: ast::DUMMY_NODE_ID,
+            attrs: new_attrs,
+            vis: vis,
+            ident: ident,
+            node: MethodImplItem(method_),
             span: mk_sp(lo, hi),
-            node: method_,
-        }
+        })
     }
 
     /// Parse trait Foo { ... }
@@ -4820,15 +4817,11 @@ impl<'a> Parser<'a> {
             }
 
             let vis = self.parse_visibility();
-            if self.eat_keyword(keywords::Type) {
-                impl_items.push(P(TypeImplItem(self.parse_typedef(
-                            method_attrs,
-                            vis))))
+            impl_items.push(if self.eat_keyword(keywords::Type) {
+                self.parse_assoc_ty_in_impl(method_attrs, vis)
             } else {
-                impl_items.push(P(MethodImplItem(self.parse_method(
-                            method_attrs,
-                            vis))));
-            }
+                self.parse_method(method_attrs, vis)
+            });
             method_attrs = vec![];
         }
         (impl_items, inner_attrs)
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 863c000dd40..a457355698d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -359,14 +359,6 @@ pub fn generics_to_string(generics: &ast::Generics) -> String {
     $to_string(|s| s.print_generics(generics))
 }
 
-pub fn ty_method_to_string(p: &ast::TypeMethod) -> String {
-    $to_string(|s| s.print_ty_method(p))
-}
-
-pub fn method_to_string(p: &ast::Method) -> String {
-    $to_string(|s| s.print_method(p))
-}
-
 pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
     $to_string(|s| s.print_fn_block_args(p))
 }
@@ -789,23 +781,24 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
-                             -> io::Result<()>
-    {
-        try!(self.print_outer_attributes(&typedef.attrs));
+    fn print_associated_type(&mut self,
+                             ident: ast::Ident,
+                             bounds: Option<&ast::TyParamBounds>,
+                             ty: Option<&ast::Ty>)
+                             -> io::Result<()> {
         try!(self.word_space("type"));
-        try!(self.print_ty_param(&typedef.ty_param));
+        try!(self.print_ident(ident));
+        if let Some(bounds) = bounds {
+            try!(self.print_bounds(":", bounds));
+        }
+        if let Some(ty) = ty {
+            try!(space(&mut self.s));
+            try!(self.word_space("="));
+            try!(self.print_type(ty));
+        }
         word(&mut self.s, ";")
     }
 
-    fn print_typedef(&mut self, typedef: &ast::Typedef) -> io::Result<()> {
-        try!(self.word_space("type"));
-        try!(self.print_ident(typedef.ident));
-        try!(space(&mut self.s));
-        try!(self.word_space("="));
-        try!(self.print_type(&*typedef.typ));
-        word(&mut self.s, ";")
-    }
 
     /// Pretty-print an item
     pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
@@ -976,18 +969,11 @@ impl<'a> State<'a> {
                 try!(self.bopen());
                 try!(self.print_inner_attributes(&item.attrs));
                 for impl_item in impl_items {
-                    match **impl_item {
-                        ast::MethodImplItem(ref meth) => {
-                            try!(self.print_method(meth));
-                        }
-                        ast::TypeImplItem(ref typ) => {
-                            try!(self.print_typedef(typ));
-                        }
-                    }
+                    try!(self.print_impl_item(impl_item));
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(unsafety, ref generics, ref bounds, ref methods) => {
+            ast::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
                 try!(self.head(""));
                 try!(self.print_visibility(item.vis));
                 try!(self.print_unsafety(unsafety));
@@ -1008,8 +994,8 @@ impl<'a> State<'a> {
                 try!(self.print_where_clause(generics));
                 try!(word(&mut self.s, " "));
                 try!(self.bopen());
-                for meth in methods {
-                    try!(self.print_trait_method(meth));
+                for trait_item in trait_items {
+                    try!(self.print_trait_item(trait_item));
                 }
                 try!(self.bclose(item.span));
             }
@@ -1241,48 +1227,65 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(m.span.lo));
-        try!(self.print_outer_attributes(&m.attrs));
+    pub fn print_ty_method(&mut self,
+                           ident: ast::Ident,
+                           m: &ast::TypeMethod)
+                           -> io::Result<()> {
         try!(self.print_ty_fn(m.abi,
                               m.unsafety,
                               &*m.decl,
-                              Some(m.ident),
+                              Some(ident),
                               &m.generics,
                               Some(&m.explicit_self.node)));
         word(&mut self.s, ";")
     }
 
-    pub fn print_trait_method(&mut self,
-                              m: &ast::TraitItem) -> io::Result<()> {
-        match *m {
-            ast::RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
-            ast::ProvidedMethod(ref m) => self.print_method(m),
-            ast::TypeTraitItem(ref t) => self.print_associated_type(t),
+    pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
+                            -> io::Result<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(ti.span.lo));
+        try!(self.print_outer_attributes(&ti.attrs));
+        match ti.node {
+            ast::RequiredMethod(ref ty_m) => {
+                self.print_ty_method(ti.ident, ty_m)
+            }
+            ast::ProvidedMethod(ref m) => {
+                self.print_method(ti.ident, &ti.attrs, ast::Inherited, m)
+            }
+            ast::TypeTraitItem(ref bounds, ref default) => {
+                self.print_associated_type(ti.ident, Some(bounds),
+                                           default.as_ref().map(|ty| &**ty))
+            }
         }
     }
 
     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
-        match *ii {
-            ast::MethodImplItem(ref m) => self.print_method(m),
-            ast::TypeImplItem(ref td) => self.print_typedef(td),
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(ii.span.lo));
+        try!(self.print_outer_attributes(&ii.attrs));
+        match ii.node {
+            ast::MethodImplItem(ref m) => {
+                self.print_method(ii.ident, &ii.attrs, ii.vis, m)
+            }
+            ast::TypeImplItem(ref ty) => {
+                self.print_associated_type(ii.ident, None, Some(ty))
+            }
         }
     }
 
-    pub fn print_method(&mut self, meth: &ast::Method) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(meth.span.lo));
-        try!(self.print_outer_attributes(&meth.attrs));
-        match meth.node {
-            ast::MethDecl(ident,
-                          ref generics,
+    pub fn print_method(&mut self,
+                        ident: ast::Ident,
+                        attrs: &[ast::Attribute],
+                        vis: ast::Visibility,
+                        meth: &ast::Method)
+                        -> io::Result<()> {
+        match *meth {
+            ast::MethDecl(ref generics,
                           abi,
                           ref explicit_self,
                           unsafety,
                           ref decl,
-                          ref body,
-                          vis) => {
+                          ref body) => {
                 try!(self.print_fn(&**decl,
                                    Some(unsafety),
                                    abi,
@@ -1291,7 +1294,7 @@ impl<'a> State<'a> {
                                    Some(&explicit_self.node),
                                    vis));
                 try!(word(&mut self.s, " "));
-                self.print_block_with_attrs(&**body, &meth.attrs)
+                self.print_block_with_attrs(&**body, attrs)
             },
             ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                             ..}) => {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 4222bd58a07..867f98f6077 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -38,7 +38,7 @@ pub enum FnKind<'a> {
     FkItemFn(Ident, &'a Generics, Unsafety, Abi),
 
     /// fn foo(&self)
-    FkMethod(Ident, &'a Generics, &'a Method),
+    FkMethod(Ident, &'a Method),
 
     /// |x, y| ...
     /// proc(x, y) ...
@@ -77,8 +77,8 @@ pub trait Visitor<'v> : Sized {
     fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
         walk_fn(self, fk, fd, b, s)
     }
-    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_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) }
+    fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) }
     fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
     fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
         walk_ty_param_bound(self, bounds)
@@ -143,13 +143,7 @@ pub fn walk_inlined_item<'v,V>(visitor: &mut V, item: &'v InlinedItem)
         IIItem(ref i) => visitor.visit_item(&**i),
         IIForeign(ref i) => visitor.visit_foreign_item(&**i),
         IITraitItem(_, ref ti) => visitor.visit_trait_item(ti),
-        IIImplItem(_, MethodImplItem(ref m)) => {
-            walk_method_helper(visitor, m)
-        }
-        IIImplItem(_, TypeImplItem(ref typedef)) => {
-            visitor.visit_ident(typedef.span, typedef.ident);
-            visitor.visit_ty(&*typedef.typ);
-        }
+        IIImplItem(_, ref ii) => visitor.visit_impl_item(ii),
     }
 }
 
@@ -202,8 +196,6 @@ 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_poly_trait_ref<'v, V>(visitor: &mut V,
                                   trait_ref: &'v PolyTraitRef,
                                   _modifier: &'v TraitBoundModifier)
@@ -213,8 +205,6 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
     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>
@@ -294,15 +284,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             }
             visitor.visit_ty(&**typ);
             for impl_item in impl_items {
-                match **impl_item {
-                    MethodImplItem(ref method) => {
-                        walk_method_helper(visitor, method)
-                    }
-                    TypeImplItem(ref typedef) => {
-                        visitor.visit_ident(typedef.span, typedef.ident);
-                        visitor.visit_ty(&*typedef.typ);
-                    }
-                }
+                visitor.visit_impl_item(impl_item);
             }
         }
         ItemStruct(ref struct_definition, ref generics) => {
@@ -561,15 +543,11 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
     }
 }
 
-pub fn walk_ty_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v TyParam) {
-    visitor.visit_ident(param.span, param.ident);
-    walk_ty_param_bounds_helper(visitor, &param.bounds);
-    walk_ty_opt(visitor, &param.default);
-}
-
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
-    for type_parameter in &*generics.ty_params {
-        walk_ty_param(visitor, type_parameter);
+    for param in &*generics.ty_params {
+        visitor.visit_ident(param.span, param.ident);
+        walk_ty_param_bounds_helper(visitor, &param.bounds);
+        walk_ty_opt(visitor, &param.default);
     }
     walk_lifetime_decls_helper(visitor, &generics.lifetimes);
     for predicate in &generics.where_clause.predicates {
@@ -618,19 +596,19 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &
 // visit_fn() and check for FkMethod().  I named this visit_method_helper()
 // because it is not a default impl of any method, though I doubt that really
 // clarifies anything. - Niko
-pub fn walk_method_helper<'v, V: Visitor<'v>>(visitor: &mut V, method: &'v Method) {
-    match method.node {
-        MethDecl(ident, ref generics, _, _, _, ref decl, ref body, _) => {
-            visitor.visit_ident(method.span, ident);
-            visitor.visit_fn(FkMethod(ident, generics, method),
+fn walk_method_helper<'v, V: Visitor<'v>>(visitor: &mut V,
+                                          id: NodeId,
+                                          ident: Ident,
+                                          span: Span,
+                                          method: &'v Method) {
+    match *method {
+        MethDecl(_, _, _, _, ref decl, ref body) => {
+            visitor.visit_ident(span, ident);
+            visitor.visit_fn(FkMethod(ident, method),
                              &**decl,
                              &**body,
-                             method.span,
-                             method.id);
-            for attr in &method.attrs {
-                visitor.visit_attribute(attr);
-            }
-
+                             span,
+                             id);
         },
         MethMac(ref mac) => visitor.visit_mac(mac)
     }
@@ -647,13 +625,13 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
         FkItemFn(_, generics, _, _) => {
             visitor.visit_generics(generics);
         }
-        FkMethod(_, generics, method) => {
-            visitor.visit_generics(generics);
-            match method.node {
-                MethDecl(_, _, _, ref explicit_self, _, _, _, _) =>
-                    visitor.visit_explicit_self(explicit_self),
-                MethMac(ref mac) =>
-                    visitor.visit_mac(mac)
+        FkMethod(_, method) => {
+            match *method {
+                MethDecl(ref generics, _, ref explicit_self, _, _, _) => {
+                    visitor.visit_generics(generics);
+                    visitor.visit_explicit_self(explicit_self);
+                }
+                MethMac(ref mac) => visitor.visit_mac(mac)
             }
         }
         FkFnBlock(..) => {}
@@ -662,25 +640,46 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
     visitor.visit_block(function_body)
 }
 
-pub fn walk_ty_method<'v, V: Visitor<'v>>(visitor: &mut V, method_type: &'v TypeMethod) {
-    visitor.visit_ident(method_type.span, method_type.ident);
-    visitor.visit_explicit_self(&method_type.explicit_self);
-    for argument_type in &method_type.decl.inputs {
-        visitor.visit_ty(&*argument_type.ty)
-    }
-    visitor.visit_generics(&method_type.generics);
-    walk_fn_ret_ty(visitor, &method_type.decl.output);
-    for attr in &method_type.attrs {
+pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
+    visitor.visit_ident(trait_item.span, trait_item.ident);
+    for attr in &trait_item.attrs {
         visitor.visit_attribute(attr);
     }
+    match trait_item.node {
+        RequiredMethod(ref method_type) => {
+            visitor.visit_explicit_self(&method_type.explicit_self);
+            visitor.visit_generics(&method_type.generics);
+            walk_fn_decl(visitor, &method_type.decl);
+        }
+        ProvidedMethod(ref method) => {
+            walk_method_helper(visitor,
+                               trait_item.id,
+                               trait_item.ident,
+                               trait_item.span,
+                               method);
+        }
+        TypeTraitItem(ref bounds, ref default) => {
+            walk_ty_param_bounds_helper(visitor, bounds);
+            walk_ty_opt(visitor, default);
+        }
+    }
 }
 
-pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v TraitItem) {
-    match *trait_method {
-        RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type),
-        ProvidedMethod(ref method) => walk_method_helper(visitor, method),
-        TypeTraitItem(ref associated_type) => {
-            walk_ty_param(visitor, &associated_type.ty_param);
+pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
+    visitor.visit_ident(impl_item.span, impl_item.ident);
+    for attr in &impl_item.attrs {
+        visitor.visit_attribute(attr);
+    }
+    match impl_item.node {
+        MethodImplItem(ref method) => {
+            walk_method_helper(visitor,
+                               impl_item.id,
+                               impl_item.ident,
+                               impl_item.span,
+                               method);
+        }
+        TypeImplItem(ref ty) => {
+            visitor.visit_ty(ty);
         }
     }
 }