about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-14 19:11:18 +0000
committerbors <bors@rust-lang.org>2014-08-14 19:11:18 +0000
commita8c8e3f80fd0355b2bb91337c6ad0bb0a38d5485 (patch)
tree6acf4c541c9321d8a304eb16f486b09755983c52 /src/libsyntax
parent404978ea722c0257cc763540c93243e8a21f82ed (diff)
parent9907fa4acc2af5b2b07d1362b3ceb29171954c58 (diff)
downloadrust-a8c8e3f80fd0355b2bb91337c6ad0bb0a38d5485.tar.gz
rust-a8c8e3f80fd0355b2bb91337c6ad0bb0a38d5485.zip
auto merge of #16286 : pcwalton/rust/associated-items-groundwork, r=nikomatsakis
methods.

This paves the way to associated items by introducing an extra level of
abstraction ("impl-or-trait item") between traits/implementations and
methods. This new abstraction is encoded in the metadata and used
throughout the compiler where appropriate.

There are no functional changes; this is purely a refactoring.

r? @nick29581
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs23
-rw-r--r--src/libsyntax/ast_map/blocks.rs18
-rw-r--r--src/libsyntax/ast_map/mod.rs152
-rw-r--r--src/libsyntax/ast_util.rs75
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs9
-rw-r--r--src/libsyntax/fold.rs25
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs29
-rw-r--r--src/libsyntax/visit.rs33
9 files changed, 256 insertions, 148 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 7d9a23e91ba..1ff8ca10fff 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -767,9 +767,14 @@ pub struct TypeMethod {
 /// doesn't have an implementation, just a signature) or provided (meaning it
 /// has a default implementation).
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum TraitMethod {
-    Required(TypeMethod),
-    Provided(Gc<Method>),
+pub enum TraitItem {
+    RequiredMethod(TypeMethod),
+    ProvidedMethod(Gc<Method>),
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum ImplItem {
+    MethodImplItem(Gc<Method>),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
@@ -1273,11 +1278,11 @@ pub enum Item_ {
               Option<TyParamBound>, // (optional) default bound not required for Self.
                                     // Currently, only Sized makes sense here.
               Vec<TraitRef> ,
-              Vec<TraitMethod>),
+              Vec<TraitItem>),
     ItemImpl(Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
-             Vec<Gc<Method>>),
+             Vec<ImplItem>),
     /// A macro invocation (which includes macro definition)
     ItemMac(Mac),
 }
@@ -1311,10 +1316,16 @@ pub enum UnboxedClosureKind {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub enum InlinedItem {
     IIItem(Gc<Item>),
-    IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
+    IITraitItem(DefId /* impl id */, InlinedTraitItem),
     IIForeign(Gc<ForeignItem>),
 }
 
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum InlinedTraitItem {
+    ProvidedInlinedTraitItem(Gc<Method>),
+    RequiredInlinedTraitItem(Gc<Method>),
+}
+
 #[cfg(test)]
 mod test {
     use serialize::json;
diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs
index 83af390c4ed..b00c6ce14b5 100644
--- a/src/libsyntax/ast_map/blocks.rs
+++ b/src/libsyntax/ast_map/blocks.rs
@@ -60,9 +60,9 @@ impl MaybeFnLike for ast::Item {
     }
 }
 
-impl MaybeFnLike for ast::TraitMethod {
+impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match *self { ast::Provided(_) => true, _ => false, }
+        match *self { ast::ProvidedMethod(_) => true, _ => false, }
     }
 }
 
@@ -97,9 +97,9 @@ impl Code {
         match node {
             ast_map::NodeItem(item) if item.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
-            ast_map::NodeTraitMethod(tm) if tm.is_fn_like() =>
+            ast_map::NodeTraitItem(tm) if tm.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
-            ast_map::NodeMethod(_) =>
+            ast_map::NodeImplItem(_) =>
                 Some(FnLikeCode(new(node))),
             ast_map::NodeExpr(e) if e.is_fn_like() =>
                 Some(FnLikeCode(new(node))),
@@ -200,11 +200,15 @@ impl FnLikeNode {
                     }),
                 _ => fail!("item FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeTraitMethod(ref t) => match **t {
-                ast::Provided(ref m) => method(&**m),
+            ast_map::NodeTraitItem(ref t) => match **t {
+                ast::ProvidedMethod(ref m) => method(&**m),
                 _ => fail!("trait method FnLikeNode that is not fn-like"),
             },
-            ast_map::NodeMethod(ref m) => method(&**m),
+            ast_map::NodeImplItem(ref ii) => {
+                match **ii {
+                    ast::MethodImplItem(ref m) => method(&**m),
+                }
+            }
             ast_map::NodeExpr(ref e) => match e.node {
                 ast::ExprFnBlock(_, ref decl, ref block) =>
                     closure(ClosureParts::new(*decl, *block, e.id, e.span)),
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 881ee4fd8d1..78afa8441c5 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -99,8 +99,8 @@ pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String {
 pub enum Node {
     NodeItem(Gc<Item>),
     NodeForeignItem(Gc<ForeignItem>),
-    NodeTraitMethod(Gc<TraitMethod>),
-    NodeMethod(Gc<Method>),
+    NodeTraitItem(Gc<TraitItem>),
+    NodeImplItem(Gc<ImplItem>),
     NodeVariant(P<Variant>),
     NodeExpr(Gc<Expr>),
     NodeStmt(Gc<Stmt>),
@@ -125,8 +125,8 @@ enum MapEntry {
     /// All the node types, with a parent ID.
     EntryItem(NodeId, Gc<Item>),
     EntryForeignItem(NodeId, Gc<ForeignItem>),
-    EntryTraitMethod(NodeId, Gc<TraitMethod>),
-    EntryMethod(NodeId, Gc<Method>),
+    EntryTraitItem(NodeId, Gc<TraitItem>),
+    EntryImplItem(NodeId, Gc<ImplItem>),
     EntryVariant(NodeId, P<Variant>),
     EntryExpr(NodeId, Gc<Expr>),
     EntryStmt(NodeId, Gc<Stmt>),
@@ -144,7 +144,7 @@ enum MapEntry {
 
 struct InlinedParent {
     path: Vec<PathElem> ,
-    /// Required by NodeTraitMethod and NodeMethod.
+    /// RequiredMethod by NodeTraitItem and NodeImplItem.
     def_id: DefId
 }
 
@@ -153,8 +153,8 @@ impl MapEntry {
         Some(match *self {
             EntryItem(id, _) => id,
             EntryForeignItem(id, _) => id,
-            EntryTraitMethod(id, _) => id,
-            EntryMethod(id, _) => id,
+            EntryTraitItem(id, _) => id,
+            EntryImplItem(id, _) => id,
             EntryVariant(id, _) => id,
             EntryExpr(id, _) => id,
             EntryStmt(id, _) => id,
@@ -172,8 +172,8 @@ impl MapEntry {
         Some(match *self {
             EntryItem(_, p) => NodeItem(p),
             EntryForeignItem(_, p) => NodeForeignItem(p),
-            EntryTraitMethod(_, p) => NodeTraitMethod(p),
-            EntryMethod(_, p) => NodeMethod(p),
+            EntryTraitItem(_, p) => NodeTraitItem(p),
+            EntryImplItem(_, p) => NodeImplItem(p),
             EntryVariant(_, p) => NodeVariant(p),
             EntryExpr(_, p) => NodeExpr(p),
             EntryStmt(_, p) => NodeStmt(p),
@@ -324,13 +324,23 @@ impl Map {
                 }
             }
             NodeForeignItem(i) => PathName(i.ident.name),
-            NodeMethod(m) => match m.node {
-                MethDecl(ident, _, _, _, _, _, _, _) => PathName(ident.name),
-                MethMac(_) => fail!("no path elem for {:?}", node)
+            NodeImplItem(ii) => {
+                match *ii {
+                    MethodImplItem(ref m) => {
+                        match m.node {
+                            MethDecl(ident, _, _, _, _, _, _, _) => {
+                                PathName(ident.name)
+                            }
+                            MethMac(_) => {
+                                fail!("no path elem for {:?}", node)
+                            }
+                        }
+                    }
+                }
             },
-            NodeTraitMethod(tm) => match *tm {
-                Required(ref m) => PathName(m.ident.name),
-                Provided(m) => match m.node {
+            NodeTraitItem(tm) => match *tm {
+                RequiredMethod(ref m) => PathName(m.ident.name),
+                ProvidedMethod(m) => match m.node {
                     MethDecl(ident, _, _, _, _, _, _, _) => {
                         PathName(ident.name)
                     }
@@ -393,11 +403,15 @@ impl Map {
         let attrs = match node {
             NodeItem(ref i) => Some(i.attrs.as_slice()),
             NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
-            NodeTraitMethod(ref tm) => match **tm {
-                Required(ref type_m) => Some(type_m.attrs.as_slice()),
-                Provided(ref m) => Some(m.attrs.as_slice())
+            NodeTraitItem(ref tm) => match **tm {
+                RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()),
+                ProvidedMethod(ref m) => Some(m.attrs.as_slice())
             },
-            NodeMethod(ref m) => Some(m.attrs.as_slice()),
+            NodeImplItem(ref ii) => {
+                match **ii {
+                    MethodImplItem(ref m) => Some(m.attrs.as_slice()),
+                }
+            }
             NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
             // unit/tuple structs take the attributes straight from
             // the struct definition.
@@ -428,13 +442,17 @@ impl Map {
         let sp = match self.find(id) {
             Some(NodeItem(item)) => item.span,
             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
-            Some(NodeTraitMethod(trait_method)) => {
+            Some(NodeTraitItem(trait_method)) => {
                 match *trait_method {
-                    Required(ref type_method) => type_method.span,
-                    Provided(ref method) => method.span,
+                    RequiredMethod(ref type_method) => type_method.span,
+                    ProvidedMethod(ref method) => method.span,
+                }
+            }
+            Some(NodeImplItem(ref impl_item)) => {
+                match **impl_item {
+                    MethodImplItem(ref method) => method.span,
                 }
             }
-            Some(NodeMethod(method)) => method.span,
             Some(NodeVariant(variant)) => variant.span,
             Some(NodeExpr(expr)) => expr.span,
             Some(NodeStmt(stmt)) => stmt.span,
@@ -532,8 +550,8 @@ impl<'a,S:Str> Iterator<NodeId> for NodesMatchingSuffix<'a,S> {
             let (p, name) = match self.map.find_entry(idx) {
                 Some(EntryItem(p, n))        => (p, n.name()),
                 Some(EntryForeignItem(p, n)) => (p, n.name()),
-                Some(EntryTraitMethod(p, n)) => (p, n.name()),
-                Some(EntryMethod(p, n))      => (p, n.name()),
+                Some(EntryTraitItem(p, n))   => (p, n.name()),
+                Some(EntryImplItem(p, n))    => (p, n.name()),
                 Some(EntryVariant(p, n))     => (p, n.name()),
                 _ => continue,
             };
@@ -553,11 +571,18 @@ 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 TraitMethod {
+impl Named for TraitItem {
+    fn name(&self) -> Name {
+        match *self {
+            RequiredMethod(ref tm) => tm.ident.name,
+            ProvidedMethod(m) => m.name(),
+        }
+    }
+}
+impl Named for ImplItem {
     fn name(&self) -> Name {
         match *self {
-            Required(ref tm) => tm.ident.name,
-            Provided(m) => m.name(),
+            MethodImplItem(ref m) => m.name(),
         }
     }
 }
@@ -616,9 +641,15 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
         assert_eq!(self.parent, i.id);
 
         match i.node {
-            ItemImpl(_, _, _, ref ms) => {
-                for &m in ms.iter() {
-                    self.insert(m.id, EntryMethod(self.parent, m));
+            ItemImpl(_, _, _, ref impl_items) => {
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        MethodImplItem(m) => {
+                            self.insert(m.id,
+                                        EntryImplItem(self.parent,
+                                                      box(GC) *impl_item));
+                        }
+                    }
                 }
             }
             ItemEnum(ref enum_definition, _) => {
@@ -649,13 +680,13 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
 
                 for tm in methods.iter() {
                     match *tm {
-                        Required(ref m) => {
-                            self.insert(m.id, EntryTraitMethod(self.parent,
+                        RequiredMethod(ref m) => {
+                            self.insert(m.id, EntryTraitItem(self.parent,
                                                                box(GC) (*tm).clone()));
                         }
-                        Provided(m) => {
-                            self.insert(m.id, EntryTraitMethod(self.parent,
-                                                               box(GC) Provided(m)));
+                        ProvidedMethod(m) => {
+                            self.insert(m.id, EntryTraitItem(self.parent,
+                                                               box(GC) ProvidedMethod(m)));
                         }
                     }
                 }
@@ -798,13 +829,18 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
     let ii = fold(&mut cx);
     match ii {
         IIItem(_) => {}
-        IIMethod(impl_did, is_provided, m) => {
-            let entry = if is_provided {
-                EntryTraitMethod(cx.parent, box(GC) Provided(m))
-            } else {
-                EntryMethod(cx.parent, m)
+        IITraitItem(impl_did, inlined_trait_item) => {
+            let (trait_item_id, entry) = match inlined_trait_item {
+                ProvidedInlinedTraitItem(m) => {
+                    (m.id,
+                     EntryTraitItem(cx.parent, box(GC) ProvidedMethod(m)))
+                }
+                RequiredInlinedTraitItem(m) => {
+                    (m.id,
+                     EntryImplItem(cx.parent, box(GC) MethodImplItem(m)))
+                }
             };
-            cx.insert(m.id, entry);
+            cx.insert(trait_item_id, entry);
             def_id = impl_did;
         }
         IIForeign(i) => {
@@ -829,8 +865,8 @@ impl<'a> NodePrinter for pprust::State<'a> {
         match *node {
             NodeItem(a)        => self.print_item(&*a),
             NodeForeignItem(a) => self.print_foreign_item(&*a),
-            NodeTraitMethod(a) => self.print_trait_method(&*a),
-            NodeMethod(a)      => self.print_method(&*a),
+            NodeTraitItem(a)   => self.print_trait_method(&*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),
@@ -870,17 +906,23 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             format!("foreign item {} (id={})", path_str, id)
         }
-        Some(NodeMethod(m)) => match m.node {
-            MethDecl(ident, _, _, _, _, _, _, _) =>
-                format!("method {} in {} (id={})",
-                        token::get_ident(ident),
-                        map.path_to_string(id), id),
-            MethMac(ref mac) =>
-                format!("method macro {} (id={})",
-                        pprust::mac_to_string(mac), id)
-        },
-        Some(NodeTraitMethod(ref tm)) => {
-            let m = ast_util::trait_method_to_ty_method(&**tm);
+        Some(NodeImplItem(ref ii)) => {
+            match **ii {
+                MethodImplItem(ref m) => {
+                    match m.node {
+                        MethDecl(ident, _, _, _, _, _, _, _) =>
+                            format!("method {} in {} (id={})",
+                                    token::get_ident(ident),
+                                    map.path_to_string(id), id),
+                        MethMac(ref mac) =>
+                            format!("method macro {} (id={})",
+                                    pprust::mac_to_string(mac), id)
+                    }
+                }
+            }
+        }
+        Some(NodeTraitItem(ref tm)) => {
+            let m = ast_util::trait_item_to_ty_method(&**tm);
             format!("method {} in {} (id={})",
                     token::get_ident(m.ident),
                     map.path_to_string(id), id)
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index cf2b5bc4063..7689646d373 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -241,51 +241,52 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
     token::gensym_ident(pretty.as_slice())
 }
 
-/// extract a TypeMethod from a TraitMethod. if the TraitMethod is
+pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
+    match method.node {
+        MethDecl(ident,
+                 ref generics,
+                 abi,
+                 explicit_self,
+                 fn_style,
+                 decl,
+                 _,
+                 vis) => {
+            TypeMethod {
+                ident: ident,
+                attrs: method.attrs.clone(),
+                fn_style: fn_style,
+                decl: decl,
+                generics: generics.clone(),
+                explicit_self: explicit_self,
+                id: method.id,
+                span: method.span,
+                vis: vis,
+                abi: abi,
+            }
+        },
+        MethMac(_) => fail!("expected non-macro method declaration")
+    }
+}
+
+/// extract a TypeMethod from a TraitItem. if the TraitItem is
 /// a default, pull out the useful fields to make a TypeMethod
 //
 // NB: to be used only after expansion is complete, and macros are gone.
-pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
+pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod {
     match *method {
-        Required(ref m) => (*m).clone(),
-        Provided(m) => {
-            match m.node {
-                MethDecl(ident,
-                         ref generics,
-                         abi,
-                         explicit_self,
-                         fn_style,
-                         decl,
-                         _,
-                         vis) => {
-                    TypeMethod {
-                        ident: ident,
-                        attrs: m.attrs.clone(),
-                        fn_style: fn_style,
-                        decl: decl,
-                        generics: generics.clone(),
-                        explicit_self: explicit_self,
-                        id: m.id,
-                        span: m.span,
-                        vis: vis,
-                        abi: abi,
-                    }
-                },
-                MethMac(_) => fail!("expected non-macro method declaration")
-            }
-
-        }
+        RequiredMethod(ref m) => (*m).clone(),
+        ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
     }
 }
 
-pub fn split_trait_methods(trait_methods: &[TraitMethod])
+pub fn split_trait_methods(trait_methods: &[TraitItem])
     -> (Vec<TypeMethod> , Vec<Gc<Method>> ) {
     let mut reqd = Vec::new();
     let mut provd = Vec::new();
     for trt_method in trait_methods.iter() {
         match *trt_method {
-            Required(ref tm) => reqd.push((*tm).clone()),
-            Provided(m) => provd.push(m)
+            RequiredMethod(ref tm) => reqd.push((*tm).clone()),
+            ProvidedMethod(m) => provd.push(m)
         }
     };
     (reqd, provd)
@@ -543,12 +544,12 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
         visit::walk_struct_def(self, struct_def, ());
     }
 
-    fn visit_trait_method(&mut self, tm: &ast::TraitMethod, _: ()) {
+    fn visit_trait_item(&mut self, tm: &ast::TraitItem, _: ()) {
         match *tm {
-            ast::Required(ref m) => self.operation.visit_id(m.id),
-            ast::Provided(ref m) => self.operation.visit_id(m.id),
+            ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
+            ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
         }
-        visit::walk_trait_method(self, tm, ());
+        visit::walk_trait_item(self, tm, ());
     }
 }
 
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 5842ca4a0d5..7a8ee6d1416 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -452,8 +452,13 @@ impl<'a> TraitDef<'a> {
             self.span,
             ident,
             (vec!(attr)).append(self.attributes.as_slice()),
-            ast::ItemImpl(trait_generics, opt_trait_ref,
-                          self_type, methods))
+            ast::ItemImpl(trait_generics,
+                          opt_trait_ref,
+                          self_type,
+                          methods.move_iter()
+                                 .map(|method| {
+                                     ast::MethodImplItem(method)
+                                 }).collect()))
     }
 
     fn expand_struct_def(&self,
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index cebe1862528..4ed2a3ed4c2 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -834,26 +834,37 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
             let struct_def = folder.fold_struct_def(*struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(ref generics, ref ifce, ty, ref methods) => {
+        ItemImpl(ref generics, ref ifce, ty, ref impl_items) => {
             ItemImpl(folder.fold_generics(generics),
                      ifce.as_ref().map(|p| folder.fold_trait_ref(p)),
                      folder.fold_ty(ty),
-                     methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
+                     impl_items.iter()
+                               .flat_map(|impl_item| {
+                                    match *impl_item {
+                                        MethodImplItem(x) => {
+                                            folder.fold_method(x)
+                                                  .move_iter()
+                                                  .map(|x| MethodImplItem(x))
+                                        }
+                                    }
+                               }).collect()
             )
         }
         ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
             let methods = methods.iter().flat_map(|method| {
                 let r = match *method {
-                    Required(ref m) =>
-                            SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
-                    Provided(method) => {
+                    RequiredMethod(ref m) => {
+                            SmallVector::one(RequiredMethod(
+                                    folder.fold_type_method(m))).move_iter()
+                    }
+                    ProvidedMethod(method) => {
                             // the awkward collect/iter idiom here is because
                             // even though an iter and a map satisfy the same trait bound,
                             // they're not actually the same type, so the method arms
                             // don't unify.
-                            let methods : SmallVector<ast::TraitMethod> =
+                            let methods : SmallVector<ast::TraitItem> =
                                 folder.fold_method(method).move_iter()
-                                .map(|m| Provided(m)).collect();
+                                .map(|m| ProvidedMethod(m)).collect();
                             methods.move_iter()
                         }
                 };
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f6db577a004..f272f7e1887 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -13,7 +13,7 @@
 use abi;
 use ast::{BareFnTy, ClosureTy};
 use ast::{StaticRegionTyParamBound, OtherRegionTyParamBound, TraitTyParamBound};
-use ast::{Provided, Public, FnStyle};
+use ast::{ProvidedMethod, Public, FnStyle};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
 use ast::{BlockCheckMode, UnBox};
@@ -33,23 +33,24 @@ use ast::{ExprVstoreUniq, Once, Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
-use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
+use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitBinary};
 use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
 use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
 use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
+use ast::{MethodImplItem};
 use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum};
 use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
-use ast::{BiRem, Required};
+use ast::{BiRem, RequiredMethod};
 use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
 use ast::{StructVariantKind, BiSub};
 use ast::StrStyle;
 use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
-use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
+use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
 use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
 use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
@@ -1238,7 +1239,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse the methods in a trait declaration
-    pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
+    pub fn parse_trait_methods(&mut self) -> Vec<TraitItem> {
         self.parse_unspanned_seq(
             &token::LBRACE,
             &token::RBRACE,
@@ -1276,7 +1277,7 @@ impl<'a> Parser<'a> {
               token::SEMI => {
                 p.bump();
                 debug!("parse_trait_methods(): parsing required method");
-                Required(TypeMethod {
+                RequiredMethod(TypeMethod {
                     ident: ident,
                     attrs: attrs,
                     fn_style: style,
@@ -1294,7 +1295,7 @@ impl<'a> Parser<'a> {
                 let (inner_attrs, body) =
                     p.parse_inner_attrs_and_block();
                 let attrs = attrs.append(inner_attrs.as_slice());
-                Provided(box(GC) ast::Method {
+                ProvidedMethod(box(GC) ast::Method {
                     attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
@@ -4243,6 +4244,18 @@ impl<'a> Parser<'a> {
         (ident, ItemTrait(tps, sized, traits, meths), None)
     }
 
+    fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
+        let mut impl_items = Vec::new();
+        self.expect(&token::LBRACE);
+        let (inner_attrs, next) = self.parse_inner_attrs_and_next();
+        let mut method_attrs = Some(next);
+        while !self.eat(&token::RBRACE) {
+            impl_items.push(MethodImplItem(self.parse_method(method_attrs)));
+            method_attrs = None;
+        }
+        (impl_items, inner_attrs)
+    }
+
     /// Parses two variants (with the region/type params always optional):
     ///    impl<T> Foo { ... }
     ///    impl<T> ToString for ~[T] { ... }
@@ -4284,18 +4297,13 @@ impl<'a> Parser<'a> {
             None
         };
 
-        let mut meths = Vec::new();
-        self.expect(&token::LBRACE);
-        let (inner_attrs, next) = self.parse_inner_attrs_and_next();
-        let mut method_attrs = Some(next);
-        while !self.eat(&token::RBRACE) {
-            meths.push(self.parse_method(method_attrs));
-            method_attrs = None;
-        }
+        let (impl_items, attrs) = self.parse_impl_items();
 
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
-        (ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
+        (ident,
+         ItemImpl(generics, opt_trait, ty, impl_items),
+         Some(attrs))
     }
 
     /// Parse a::B<String,int>
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 4ee73406f03..c573cc0c0ad 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -10,9 +10,9 @@
 
 use abi;
 use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
-use ast::{FnUnboxedClosureKind, P, OtherRegionTyParamBound};
+use ast::{FnUnboxedClosureKind, MethodImplItem, P, OtherRegionTyParamBound};
 use ast::{StaticRegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
-use ast::{UnboxedFnTyParamBound, Required, Provided};
+use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
 use ast;
 use ast_util;
 use owned_slice::OwnedSlice;
@@ -787,7 +787,10 @@ impl<'a> State<'a> {
                                        item.span));
             }
 
-            ast::ItemImpl(ref generics, ref opt_trait, ref ty, ref methods) => {
+            ast::ItemImpl(ref generics,
+                          ref opt_trait,
+                          ref ty,
+                          ref impl_items) => {
                 try!(self.head(visibility_qualified(item.vis,
                                                     "impl").as_slice()));
                 if generics.is_parameterized() {
@@ -809,8 +812,12 @@ impl<'a> State<'a> {
                 try!(space(&mut self.s));
                 try!(self.bopen());
                 try!(self.print_inner_attributes(item.attrs.as_slice()));
-                for meth in methods.iter() {
-                    try!(self.print_method(&**meth));
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(meth) => {
+                            try!(self.print_method(&*meth));
+                        }
+                    }
                 }
                 try!(self.bclose(item.span));
             }
@@ -1061,10 +1068,16 @@ impl<'a> State<'a> {
     }
 
     pub fn print_trait_method(&mut self,
-                              m: &ast::TraitMethod) -> IoResult<()> {
+                              m: &ast::TraitItem) -> IoResult<()> {
         match *m {
-            Required(ref ty_m) => self.print_ty_method(ty_m),
-            Provided(ref m) => self.print_method(&**m)
+            RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
+            ProvidedMethod(ref m) => self.print_method(&**m)
+        }
+    }
+
+    pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> {
+        match *ii {
+            MethodImplItem(ref m) => self.print_method(&**m),
         }
     }
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 79a870422a6..18cbf797d03 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -99,7 +99,7 @@ pub trait Visitor<E: Clone> {
         walk_fn(self, fk, fd, b, s, e)
     }
     fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
-    fn visit_trait_method(&mut self, t: &TraitMethod, e: E) { walk_trait_method(self, t, e) }
+    fn visit_trait_item(&mut self, t: &TraitItem, e: E) { walk_trait_item(self, t, e) }
     fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics, _: NodeId, e: E) {
         walk_struct_def(self, s, e)
     }
@@ -148,7 +148,16 @@ pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
     match *item {
         IIItem(i) => visitor.visit_item(&*i, env),
         IIForeign(i) => visitor.visit_foreign_item(&*i, env),
-        IIMethod(_, _, m) => walk_method_helper(visitor, &*m, env),
+        IITraitItem(_, iti) => {
+            match iti {
+                ProvidedInlinedTraitItem(m) => {
+                    walk_method_helper(visitor, &*m, env)
+                }
+                RequiredInlinedTraitItem(m) => {
+                    walk_method_helper(visitor, &*m, env)
+                }
+            }
+        }
     }
 }
 
@@ -269,7 +278,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
         ItemImpl(ref type_parameters,
                  ref trait_reference,
                  typ,
-                 ref methods) => {
+                 ref impl_items) => {
             visitor.visit_generics(type_parameters, env.clone());
             match *trait_reference {
                 Some(ref trait_reference) => walk_trait_ref_helper(visitor,
@@ -277,8 +286,12 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                 None => ()
             }
             visitor.visit_ty(&*typ, env.clone());
-            for method in methods.iter() {
-                walk_method_helper(visitor, &**method, env.clone())
+            for impl_item in impl_items.iter() {
+                match *impl_item {
+                    MethodImplItem(method) => {
+                        walk_method_helper(visitor, &*method, env.clone())
+                    }
+                }
             }
         }
         ItemStruct(ref struct_definition, ref generics) => {
@@ -297,7 +310,7 @@ pub fn walk_item<E: Clone, V: Visitor<E>>(visitor: &mut V, item: &Item, env: E)
                                    env.clone())
             }
             for method in methods.iter() {
-                visitor.visit_trait_method(method, env.clone())
+                visitor.visit_trait_item(method, env.clone())
             }
         }
         ItemMac(ref macro) => visitor.visit_mac(macro, env.clone()),
@@ -626,14 +639,14 @@ pub fn walk_ty_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
     }
 }
 
-pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
-                                                  trait_method: &TraitMethod,
+pub fn walk_trait_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
+                                                  trait_method: &TraitItem,
                                                   env: E) {
     match *trait_method {
-        Required(ref method_type) => {
+        RequiredMethod(ref method_type) => {
             visitor.visit_ty_method(method_type, env)
         }
-        Provided(ref method) => walk_method_helper(visitor, &**method, env),
+        ProvidedMethod(ref method) => walk_method_helper(visitor, &**method, env),
     }
 }