about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2014-07-11 21:22:11 -0700
committerJohn Clements <clements@racket-lang.org>2014-07-13 10:08:27 -0700
commitb0b4b3122a4af7bf9b361c8f646da4a120e7ba38 (patch)
treed3e0fcb19160fcdc2f2977bebc647af9587cf512
parente178ebf681d532c1c965883ae34788713f748960 (diff)
downloadrust-b0b4b3122a4af7bf9b361c8f646da4a120e7ba38.tar.gz
rust-b0b4b3122a4af7bf9b361c8f646da4a120e7ba38.zip
refactor Method definition to make space for macros
This change propagates to many locations, but because of the
Macro Exterminator (or, more properly, the invariant that it
protects), macro invocations can't occur downstream of expansion.
This means that in librustc and librustdoc, extracting the
desired field can simply assume that it can't be a macro
invocation. Functions in ast_util abstract over this check.
-rw-r--r--src/librustc/metadata/encoder.rs4
-rw-r--r--src/librustc/middle/astencode.rs2
-rw-r--r--src/librustc/middle/dead.rs6
-rw-r--r--src/librustc/middle/effect.rs3
-rw-r--r--src/librustc/middle/privacy.rs19
-rw-r--r--src/librustc/middle/reachable.rs8
-rw-r--r--src/librustc/middle/resolve.rs17
-rw-r--r--src/librustc/middle/save/mod.rs13
-rw-r--r--src/librustc/middle/trans/debuginfo.rs16
-rw-r--r--src/librustc/middle/trans/inline.rs5
-rw-r--r--src/librustc/middle/trans/meth.rs9
-rw-r--r--src/librustc/middle/trans/monomorphize.rs7
-rw-r--r--src/librustc/middle/typeck/check/mod.rs10
-rw-r--r--src/librustc/middle/typeck/collect.rs29
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs13
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/libsyntax/ast.rs19
-rw-r--r--src/libsyntax/ast_map.rs32
-rw-r--r--src/libsyntax/ast_util.rs75
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs14
-rw-r--r--src/libsyntax/ext/expand.rs28
-rw-r--r--src/libsyntax/fold.rs21
-rw-r--r--src/libsyntax/parse/parser.rs16
-rw-r--r--src/libsyntax/print/pprust.rs31
-rw-r--r--src/libsyntax/visit.rs32
25 files changed, 277 insertions, 173 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 493fd575a84..6cb0ab51ca1 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -799,7 +799,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
         } else {
             encode_symbol(ecx, ebml_w, m.def_id.node);
         }
-        encode_method_argument_names(ebml_w, &*ast_method.decl);
+        encode_method_argument_names(ebml_w, method_fn_decl(&*ast_method));
     }
 
     ebml_w.end_tag();
@@ -1241,7 +1241,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                     encode_method_sort(ebml_w, 'p');
                     encode_inlined_item(ecx, ebml_w,
                                         IIMethodRef(def_id, true, &*m));
-                    encode_method_argument_names(ebml_w, &*m.decl);
+                    encode_method_argument_names(ebml_w, method_fn_decl(m));
                 }
             }
 
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index fb2b4951ea3..8fa7d7c2aaa 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -136,7 +136,7 @@ pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
         let ident = match ii {
             ast::IIItem(i) => i.ident,
             ast::IIForeign(i) => i.ident,
-            ast::IIMethod(_, _, m) => m.ident,
+            ast::IIMethod(_, _, m) => ast_util::method_ident(&*m),
         };
         debug!("Fn named: {}", token::get_ident(ident));
         debug!("< Decoded inlined fn: {}::{}",
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 9ec167ee826..d84c62f744e 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -22,6 +22,7 @@ use util::nodemap::NodeSet;
 use std::collections::HashSet;
 use syntax::ast;
 use syntax::ast_map;
+use syntax::ast_util;
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
@@ -212,7 +213,7 @@ impl<'a> MarkSymbolVisitor<'a> {
                 visit::walk_trait_method(self, &*trait_method, ctxt);
             }
             ast_map::NodeMethod(method) => {
-                visit::walk_block(self, &*method.body, ctxt);
+                visit::walk_block(self, ast_util::method_body(&*method), ctxt);
             }
             ast_map::NodeForeignItem(foreign_item) => {
                 visit::walk_foreign_item(self, &*foreign_item, ctxt);
@@ -520,7 +521,8 @@ impl<'a> Visitor<()> for DeadVisitor<'a> {
     // Overwrite so that we don't warn the trait method itself.
     fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
         match *trait_method {
-            ast::Provided(ref method) => visit::walk_block(self, &*method.body, ()),
+            ast::Provided(ref method) => visit::walk_block(self,
+                                                           ast_util::method_body(&**method), ()),
             ast::Required(_) => ()
         }
     }
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 782a380e23a..415135a2d04 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -17,6 +17,7 @@ use middle::typeck::MethodCall;
 use util::ppaux;
 
 use syntax::ast;
+use syntax::ast_util;
 use syntax::codemap::Span;
 use syntax::visit;
 use syntax::visit::Visitor;
@@ -94,7 +95,7 @@ impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
             visit::FkItemFn(_, _, fn_style, _) =>
                 (true, fn_style == ast::UnsafeFn),
             visit::FkMethod(_, _, method) =>
-                (true, method.fn_style == ast::UnsafeFn),
+                (true, ast_util::method_fn_style(method) == ast::UnsafeFn),
             _ => (false, false),
         };
 
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 7630321bd55..580e7b2db57 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -26,6 +26,7 @@ use util::nodemap::{NodeMap, NodeSet};
 
 use syntax::ast;
 use syntax::ast_map;
+use syntax::ast_util;
 use syntax::ast_util::{is_local, local_def};
 use syntax::attr;
 use syntax::codemap::Span;
@@ -263,10 +264,10 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
 
                 if public_ty || public_trait {
                     for method in methods.iter() {
-                        let meth_public = match method.explicit_self.node {
+                        let meth_public = match ast_util::method_explicit_self(&**method).node {
                             ast::SelfStatic => public_ty,
                             _ => true,
-                        } && method.vis == ast::Public;
+                        } && ast_util::method_vis(&**method) == ast::Public;
                         if meth_public || tr.is_some() {
                             self.exported_items.insert(method.id);
                         }
@@ -456,8 +457,8 @@ impl<'a> PrivacyVisitor<'a> {
                     let imp = self.tcx.map.get_parent_did(closest_private_id);
                     match ty::impl_trait_ref(self.tcx, imp) {
                         Some(..) => return Allowable,
-                        _ if m.vis == ast::Public => return Allowable,
-                        _ => m.vis
+                        _ if ast_util::method_vis(&**m) == ast::Public => return Allowable,
+                        _ => ast_util::method_vis(&**m)
                     }
                 }
                 Some(ast_map::NodeTraitMethod(_)) => {
@@ -1078,7 +1079,7 @@ impl<'a> SanePrivacyVisitor<'a> {
                                 "visibility qualifiers have no effect on trait \
                                  impls");
                 for m in methods.iter() {
-                    check_inherited(m.span, m.vis, "");
+                    check_inherited(m.span, ast_util::method_vis(&**m), "");
                 }
             }
 
@@ -1110,7 +1111,7 @@ impl<'a> SanePrivacyVisitor<'a> {
                 for m in methods.iter() {
                     match *m {
                         ast::Provided(ref m) => {
-                            check_inherited(m.span, m.vis,
+                            check_inherited(m.span, ast_util::method_vis(&**m),
                                             "unnecessary visibility");
                         }
                         ast::Required(ref m) => {
@@ -1148,7 +1149,7 @@ impl<'a> SanePrivacyVisitor<'a> {
         match item.node {
             ast::ItemImpl(_, _, _, ref methods) => {
                 for m in methods.iter() {
-                    check_inherited(tcx, m.span, m.vis);
+                    check_inherited(tcx, m.span, ast_util::method_vis(&**m));
                 }
             }
             ast::ItemForeignMod(ref fm) => {
@@ -1174,7 +1175,7 @@ impl<'a> SanePrivacyVisitor<'a> {
                     match *m {
                         ast::Required(..) => {}
                         ast::Provided(ref m) => check_inherited(tcx, m.span,
-                                                                m.vis),
+                                                                ast_util::method_vis(&**m)),
                     }
                 }
             }
@@ -1344,7 +1345,7 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
                     for method in methods.iter() {
-                        if method.explicit_self.node == ast::SelfStatic &&
+                        if ast_util::method_explicit_self(&**method).node == ast::SelfStatic &&
                             self.exported_items.contains(&method.id) {
                             found_pub_static = true;
                             visit::walk_method_helper(self, &**method, ());
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 26bb0b62cb0..d9324574da7 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -68,7 +68,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
 fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
                            impl_src: ast::DefId) -> bool {
     if attributes_specify_inlining(method.attrs.as_slice()) ||
-        generics_require_inlining(&method.generics) {
+        generics_require_inlining(ast_util::method_generics(&*method)) {
         return true
     }
     if is_local(impl_src) {
@@ -200,7 +200,7 @@ impl<'a> ReachableContext<'a> {
                 }
             }
             Some(ast_map::NodeMethod(method)) => {
-                if generics_require_inlining(&method.generics) ||
+                if generics_require_inlining(ast_util::method_generics(&*method)) ||
                         attributes_specify_inlining(method.attrs.as_slice()) {
                     true
                 } else {
@@ -316,14 +316,14 @@ impl<'a> ReachableContext<'a> {
                         // Keep going, nothing to get exported
                     }
                     ast::Provided(ref method) => {
-                        visit::walk_block(self, &*method.body, ())
+                        visit::walk_block(self, ast_util::method_body(&**method), ())
                     }
                 }
             }
             ast_map::NodeMethod(method) => {
                 let did = self.tcx.map.get_parent_did(search_item);
                 if method_might_be_inlined(self.tcx, &*method, did) {
-                    visit::walk_block(self, &*method.body, ())
+                    visit::walk_block(self, ast_util::method_body(&*method), ())
                 }
             }
             // Nothing to recurse on for these
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 4655507f5d1..6c6ac81b985 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -22,6 +22,7 @@ use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
 
 use syntax::ast::*;
 use syntax::ast;
+use syntax::ast_util;
 use syntax::ast_util::{local_def};
 use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
 use syntax::ext::mtwt;
@@ -1298,20 +1299,20 @@ impl<'a> Resolver<'a> {
                         // For each method...
                         for method in methods.iter() {
                             // Add the method to the module.
-                            let ident = method.ident;
+                            let ident = ast_util::method_ident(&**method);
                             let method_name_bindings =
                                 self.add_child(ident,
                                                new_parent.clone(),
                                                ForbidDuplicateValues,
                                                method.span);
-                            let def = match method.explicit_self.node {
+                            let def = match ast_util::method_explicit_self(&**method).node {
                                 SelfStatic => {
                                     // Static methods become
                                     // `def_static_method`s.
                                     DefStaticMethod(local_def(method.id),
                                                       FromImpl(local_def(
                                                         item.id)),
-                                                      method.fn_style)
+                                                    ast_util::method_fn_style(&**method))
                                 }
                                 _ => {
                                     // Non-static methods become
@@ -1320,7 +1321,7 @@ impl<'a> Resolver<'a> {
                                 }
                             };
 
-                            let is_public = method.vis == ast::Public;
+                            let is_public = ast_util::method_vis(&**method) == ast::Public;
                             method_name_bindings.define_value(def,
                                                               method.span,
                                                               is_public);
@@ -4003,13 +4004,15 @@ impl<'a> Resolver<'a> {
     fn resolve_method(&mut self,
                       rib_kind: RibKind,
                       method: &Method) {
-        let method_generics = &method.generics;
+        let method_generics = ast_util::method_generics(method);
         let type_parameters = HasTypeParameters(method_generics,
                                                 FnSpace,
                                                 method.id,
                                                 rib_kind);
 
-        self.resolve_function(rib_kind, Some(method.decl), type_parameters, method.body);
+        self.resolve_function(rib_kind, Some(ast_util::method_fn_decl(method)),
+                              type_parameters,
+                              ast_util::method_body(method));
     }
 
     fn with_current_self_type<T>(&mut self, self_type: &Ty, f: |&mut Resolver| -> T) -> T {
@@ -4080,7 +4083,7 @@ impl<'a> Resolver<'a> {
     fn check_trait_method(&self, method: &Method) {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         for &(did, ref trait_ref) in self.current_trait_ref.iter() {
-            let method_name = method.ident.name;
+            let method_name = ast_util::method_ident(method).name;
 
             if self.method_map.borrow().find(&(method_name, did)).is_none() {
                 let path_str = self.path_idents_to_string(&trait_ref.path);
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
index d16e2bbf66b..a492b4ab952 100644
--- a/src/librustc/middle/save/mod.rs
+++ b/src/librustc/middle/save/mod.rs
@@ -333,7 +333,7 @@ impl <'l> DxrVisitor<'l> {
             },
         };
 
-        qualname.push_str(get_ident(method.ident).get());
+        qualname.push_str(get_ident(ast_util::method_ident(&*method)).get());
         let qualname = qualname.as_slice();
 
         // record the decl for this def (if it has one)
@@ -349,17 +349,18 @@ impl <'l> DxrVisitor<'l> {
                             decl_id,
                             scope_id);
 
-        self.process_formals(&method.decl.inputs, qualname, e);
+        let m_decl = ast_util::method_fn_decl(&*method);
+        self.process_formals(&m_decl.inputs, qualname, e);
 
         // walk arg and return types
-        for arg in method.decl.inputs.iter() {
+        for arg in m_decl.inputs.iter() {
             self.visit_ty(&*arg.ty, e);
         }
-        self.visit_ty(&*method.decl.output, e);
+        self.visit_ty(m_decl.output, e);
         // walk the fn body
-        self.visit_block(&*method.body, DxrVisitorEnv::new_nested(method.id));
+        self.visit_block(ast_util::method_body(&*method), DxrVisitorEnv::new_nested(method.id));
 
-        self.process_generic_params(&method.generics,
+        self.process_generic_params(ast_util::method_generics(&*method),
                                     method.span,
                                     qualname,
                                     method.id,
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 9acd0487199..e3af8f93ead 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -1138,10 +1138,10 @@ pub fn create_function_debug_context(cx: &CrateContext,
             }
         }
         ast_map::NodeMethod(ref method) => {
-            (method.ident,
-             method.decl,
-             &method.generics,
-             method.body,
+            (ast_util::method_ident(&**method),
+             ast_util::method_fn_decl(&**method),
+             ast_util::method_generics(&**method),
+             ast_util::method_body(&**method),
              method.span,
              true)
         }
@@ -1167,10 +1167,10 @@ pub fn create_function_debug_context(cx: &CrateContext,
         ast_map::NodeTraitMethod(ref trait_method) => {
             match **trait_method {
                 ast::Provided(ref method) => {
-                    (method.ident,
-                     method.decl,
-                     &method.generics,
-                     method.body,
+                    (ast_util::method_ident(&**method),
+                     ast_util::method_fn_decl(&**method),
+                     ast_util::method_generics(&**method),
+                     ast_util::method_body(&**method),
                      method.span,
                      true)
                 }
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index 2ebbc2f5340..f11577482b6 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -128,11 +128,12 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
             let unparameterized =
                 impl_tpt.generics.types.is_empty() &&
-                mth.generics.ty_params.is_empty();
+                ast_util::method_generics(&*mth).ty_params.is_empty();
 
           if unparameterized {
               let llfn = get_item_val(ccx, mth.id);
-              trans_fn(ccx, &*mth.decl, &*mth.body, llfn,
+              trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+                       ast_util::method_body(&*mth), llfn,
                        &param_substs::empty(), mth.id, []);
           }
           local_def(mth.id)
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index c79e435707a..6b54556bbe0 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -38,7 +38,7 @@ use std::c_str::ToCStr;
 use std::gc::Gc;
 use syntax::abi::Rust;
 use syntax::parse::token;
-use syntax::{ast, ast_map, visit};
+use syntax::{ast, ast_map, visit, ast_util};
 
 /**
 The main "translation" pass for methods.  Generates code
@@ -66,9 +66,10 @@ pub fn trans_impl(ccx: &CrateContext,
         return;
     }
     for method in methods.iter() {
-        if method.generics.ty_params.len() == 0u {
+        if ast_util::method_generics(&**method).ty_params.len() == 0u {
             let llfn = get_item_val(ccx, method.id);
-            trans_fn(ccx, &*method.decl, &*method.body,
+            trans_fn(ccx, ast_util::method_fn_decl(&**method),
+                     ast_util::method_body(&**method),
                      llfn, &param_substs::empty(), method.id, []);
         } else {
             let mut v = TransItemVisitor{ ccx: ccx };
@@ -160,7 +161,7 @@ pub fn trans_static_method_callee(bcx: &Block,
             ast_map::NodeTraitMethod(method) => {
                 let ident = match *method {
                     ast::Required(ref m) => m.ident,
-                    ast::Provided(ref m) => m.ident
+                    ast::Provided(ref m) => ast_util::method_ident(&**m)
                 };
                 ident.name
             }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 82dfd293205..01544214ccf 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -25,6 +25,7 @@ use util::ppaux::Repr;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_map;
+use syntax::ast_util;
 use syntax::ast_util::local_def;
 use std::hash::{sip, Hash};
 
@@ -181,7 +182,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeMethod(mth) => {
             let d = mk_lldecl();
             set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-            trans_fn(ccx, &*mth.decl, &*mth.body, d, &psubsts, mth.id, []);
+            trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+                     ast_util::method_body(&*mth), d, &psubsts, mth.id, []);
             d
         }
         ast_map::NodeTraitMethod(method) => {
@@ -189,7 +191,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                 ast::Provided(mth) => {
                     let d = mk_lldecl();
                     set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-                    trans_fn(ccx, &*mth.decl, &*mth.body, d, &psubsts, mth.id, []);
+                    trans_fn(ccx, ast_util::method_fn_decl(&*mth),
+                             ast_util::method_body(&*mth), d, &psubsts, mth.id, []);
                     d
                 }
                 _ => {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index cdf434f4099..fb29baeea73 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -757,14 +757,16 @@ fn check_method_body(ccx: &CrateCtxt,
     let method_def_id = local_def(method.id);
     let method_ty = ty::method(ccx.tcx, method_def_id);
     let method_generics = &method_ty.generics;
+    let m_body = ast_util::method_body(&*method);
 
     let param_env = ty::construct_parameter_environment(ccx.tcx,
                                                         method_generics,
-                                                        method.body.id);
+                                                        m_body.id);
 
     let fty = ty::node_id_to_type(ccx.tcx, method.id);
 
-    check_bare_fn(ccx, &*method.decl, &*method.body, method.id, fty, param_env);
+    check_bare_fn(ccx, ast_util::method_fn_decl(&*method),
+                  m_body, method.id, fty, param_env);
 }
 
 fn check_impl_methods_against_trait(ccx: &CrateCtxt,
@@ -792,7 +794,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
                 compare_impl_method(ccx.tcx,
                                     &*impl_method_ty,
                                     impl_method.span,
-                                    impl_method.body.id,
+                                    ast_util::method_body(&**impl_method).id,
                                     &**trait_method_ty,
                                     &impl_trait_ref.substs);
             }
@@ -815,7 +817,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
     for trait_method in trait_methods.iter() {
         let is_implemented =
             impl_methods.iter().any(
-                |m| m.ident.name == trait_method.ident.name);
+                |m| ast_util::method_ident(&**m).name == trait_method.ident.name);
         let is_provided =
             provided_methods.iter().any(
                 |m| m.ident.name == trait_method.ident.name);
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index b6cdeb92aa3..9f08dc2c924 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -57,7 +57,8 @@ use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound};
 use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
 use syntax::ast;
 use syntax::ast_map;
-use syntax::ast_util::{local_def, split_trait_methods};
+use syntax::ast_util;
+use syntax::ast_util::{local_def, method_ident, split_trait_methods};
 use syntax::codemap::Span;
 use syntax::codemap;
 use syntax::owned_slice::OwnedSlice;
@@ -213,8 +214,11 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                             &ast::Provided(ref m) => {
                                 ty_method_of_trait_method(
                                     ccx, trait_id, &trait_def.generics,
-                                    &m.id, &m.ident, &m.explicit_self,
-                                    &m.generics, &m.fn_style, &*m.decl)
+                                    &m.id, &ast_util::method_ident(&**m),
+                                    ast_util::method_explicit_self(&**m),
+                                    ast_util::method_generics(&**m),
+                                    &ast_util::method_fn_style(&**m),
+                                    ast_util::method_fn_decl(&**m))
                             }
                         });
 
@@ -330,7 +334,7 @@ fn convert_methods(ccx: &CrateCtxt,
     let tcx = ccx.tcx;
     let mut seen_methods = HashSet::new();
     for m in ms.iter() {
-        if !seen_methods.insert(m.ident.repr(ccx.tcx)) {
+        if !seen_methods.insert(ast_util::method_ident(&**m).repr(tcx)) {
             tcx.sess.span_err(m.span, "duplicate method in trait impl");
         }
 
@@ -342,9 +346,9 @@ fn convert_methods(ccx: &CrateCtxt,
                                        rcvr_visibility));
         let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
         debug!("method {} (id {}) has type {}",
-                m.ident.repr(ccx.tcx),
+                method_ident(&**m).repr(tcx),
                 m.id,
-                fty.repr(ccx.tcx));
+                fty.repr(tcx));
         tcx.tcache.borrow_mut().insert(
             local_def(m.id),
             Polytype {
@@ -365,23 +369,24 @@ fn convert_methods(ccx: &CrateCtxt,
                     rcvr_visibility: ast::Visibility)
                     -> ty::Method
     {
-        let fty = astconv::ty_of_method(ccx, m.id, m.fn_style,
+        let fty = astconv::ty_of_method(ccx, m.id, ast_util::method_fn_style(&*m),
                                         untransformed_rcvr_ty,
-                                        m.explicit_self, &*m.decl);
+                                        *ast_util::method_explicit_self(&*m),
+                                        ast_util::method_fn_decl(&*m));
 
         // if the method specifies a visibility, use that, otherwise
         // inherit the visibility from the impl (so `foo` in `pub impl
         // { fn foo(); }` is public, but private in `priv impl { fn
         // foo(); }`).
-        let method_vis = m.vis.inherit_from(rcvr_visibility);
+        let method_vis = ast_util::method_vis(&*m).inherit_from(rcvr_visibility);
 
         let m_ty_generics =
-            ty_generics_for_fn_or_method(ccx, &m.generics,
+            ty_generics_for_fn_or_method(ccx, ast_util::method_generics(&*m),
                                          (*rcvr_ty_generics).clone());
-        ty::Method::new(m.ident,
+        ty::Method::new(ast_util::method_ident(&*m),
                         m_ty_generics,
                         fty,
-                        m.explicit_self.node,
+                        ast_util::method_explicit_self(&*m).node,
                         method_vis,
                         local_def(m.id),
                         container,
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index b0c9900be90..bdd6d96f394 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -693,15 +693,18 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        ast::ItemFn(ref fn_decl, ref pur, _, ref gen, _) => {
+                        ast::ItemFn(fn_decl, ref pur, _, ref gen, _) => {
                             Some((fn_decl, gen, *pur, item.ident, None, item.span))
                         },
                         _ => None
                     }
                 }
                 ast_map::NodeMethod(ref m) => {
-                    Some((&m.decl, &m.generics, m.fn_style,
-                          m.ident, Some(m.explicit_self.node), m.span))
+                    Some((ast_util::method_fn_decl(&**m),
+                          ast_util::method_generics(&**m),
+                          ast_util::method_fn_style(&**m),
+                          ast_util::method_ident(&**m),
+                          Some(ast_util::method_explicit_self(&**m).node), m.span))
                 },
                 _ => None
             },
@@ -711,7 +714,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
                                     = node_inner.expect("expect item fn");
         let taken = lifetimes_in_scope(self.tcx, scope_id);
         let life_giver = LifeGiver::with_taken(taken.as_slice());
-        let rebuilder = Rebuilder::new(self.tcx, *fn_decl, expl_self,
+        let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
                                        generics, same_regions, &life_giver);
         let (fn_decl, expl_self, generics) = rebuilder.rebuild();
         self.give_expl_lifetime_param(&fn_decl, fn_style, ident,
@@ -1452,7 +1455,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
                 _ => None
             },
             ast_map::NodeMethod(m) => {
-                taken.push_all(m.generics.lifetimes.as_slice());
+                taken.push_all(ast_util::method_generics(&*m).lifetimes.as_slice());
                 Some(m.id)
             },
             _ => None
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a5c6725bd81..2e3bb2eef7d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -695,29 +695,30 @@ pub struct Method {
 
 impl Clean<Item> for ast::Method {
     fn clean(&self) -> Item {
-        let inputs = match self.explicit_self.node {
-            ast::SelfStatic => self.decl.inputs.as_slice(),
-            _ => self.decl.inputs.slice_from(1)
+        let fn_decl = ast_util::method_fn_decl(self);
+        let inputs = match ast_util::method_explicit_self(self).node {
+            ast::SelfStatic => fn_decl.inputs.as_slice(),
+            _ => fn_decl.inputs.slice_from(1)
         };
         let decl = FnDecl {
             inputs: Arguments {
                 values: inputs.iter().map(|x| x.clean()).collect(),
             },
-            output: (self.decl.output.clean()),
-            cf: self.decl.cf.clean(),
+            output: (fn_decl.output.clean()),
+            cf: fn_decl.cf.clean(),
             attrs: Vec::new()
         };
         Item {
-            name: Some(self.ident.clean()),
+            name: Some(ast_util::method_ident(self).clean()),
             attrs: self.attrs.clean().move_iter().collect(),
             source: self.span.clean(),
             def_id: ast_util::local_def(self.id),
-            visibility: self.vis.clean(),
+            visibility: ast_util::method_vis(self).clean(),
             stability: get_stability(ast_util::local_def(self.id)),
             inner: MethodItem(Method {
-                generics: self.generics.clean(),
-                self_: self.explicit_self.node.clean(),
-                fn_style: self.fn_style.clone(),
+                generics: ast_util::method_generics(self).clean(),
+                self_: ast_util::method_explicit_self(self).node.clean(),
+                fn_style: ast_util::method_fn_style(self).clone(),
                 decl: decl,
             }),
         }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index dd830401443..98318312d58 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -633,6 +633,8 @@ pub type Mac = Spanned<Mac_>;
 /// There's only one flavor, now, so this could presumably be simplified.
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
 pub enum Mac_ {
+    // NB: the additional ident for a macro_rules-style macro is actually
+    // stored in the enclosing item. Oog.
     MacInvocTT(Path, Vec<TokenTree> , SyntaxContext),   // new macro-invocation
 }
 
@@ -950,19 +952,20 @@ pub enum ExplicitSelf_ {
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
 
-// Represents a method declaration
 #[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
 pub struct Method {
-    pub ident: Ident,
     pub attrs: Vec<Attribute>,
-    pub generics: Generics,
-    pub explicit_self: ExplicitSelf,
-    pub fn_style: FnStyle,
-    pub decl: P<FnDecl>,
-    pub body: P<Block>,
     pub id: NodeId,
     pub span: Span,
-    pub vis: Visibility,
+    pub node: Method_
+}
+
+#[deriving(PartialEq, Eq, Encodable, Decodable, Hash)]
+pub enum Method_ {
+    /// Represents a method declaration
+    MethDecl(Ident, Generics, ExplicitSelf, FnStyle, P<FnDecl>, P<Block>, Visibility),
+    /// Represents a macro in method position
+    MethMac(Mac),
 }
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index de2ecd9a264..d0a0c4fe380 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -304,8 +304,10 @@ impl Map {
         }
     }
 
+    /// returns the name associated with the given NodeId's AST
     pub fn get_path_elem(&self, id: NodeId) -> PathElem {
-        match self.get(id) {
+        let node = self.get(id);
+        match node {
             NodeItem(item) => {
                 match item.node {
                     ItemMod(_) | ItemForeignMod(_) => {
@@ -315,13 +317,19 @@ impl Map {
                 }
             }
             NodeForeignItem(i) => PathName(i.ident.name),
-            NodeMethod(m) => PathName(m.ident.name),
+            NodeMethod(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(ref m) => PathName(m.ident.name)
+                Provided(m) => match m.node {
+                    MethDecl(ident, _, _, _, _, _, _) => PathName(ident.name),
+                    MethMac(_) => fail!("no path elem for {:?}", node),
+                }
             },
             NodeVariant(v) => PathName(v.node.name.name),
-            node => fail!("no path elem for {:?}", node)
+            _ => fail!("no path elem for {:?}", node)
         }
     }
 
@@ -369,6 +377,8 @@ impl Map {
         }
     }
 
+    /// Given a node ID and a closure, apply the closure to the array
+    /// of attributes associated with the AST corresponding to the Node ID
     pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
         let node = self.get(id);
         let attrs = match node {
@@ -695,11 +705,15 @@ 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)) => {
-            format!("method {} in {} (id={})",
-                    token::get_ident(m.ident),
-                    map.path_to_string(id), 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);
             format!("method {} in {} (id={})",
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index cd38c9b3e98..a18d8a81ef4 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -240,32 +240,31 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
     token::gensym_ident(pretty.as_slice())
 }
 
-pub fn public_methods(ms: Vec<Gc<Method>> ) -> Vec<Gc<Method>> {
-    ms.move_iter().filter(|m| {
-        match m.vis {
-            Public => true,
-            _   => false
-        }
-    }).collect()
-}
-
 /// extract a TypeMethod from a TraitMethod. if the TraitMethod 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 {
     match *method {
         Required(ref m) => (*m).clone(),
-        Provided(ref m) => {
-            TypeMethod {
-                ident: m.ident,
-                attrs: m.attrs.clone(),
-                fn_style: m.fn_style,
-                decl: m.decl,
-                generics: m.generics.clone(),
-                explicit_self: m.explicit_self,
-                id: m.id,
-                span: m.span,
-                vis: m.vis,
+        Provided(m) => {
+            match m.node {
+                MethDecl(ident, ref generics, 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,
+                    }
+                },
+                MethMac(_) => fail!("expected non-macro method declaration")
             }
+
         }
     }
 }
@@ -346,6 +345,9 @@ pub trait IdVisitingOperation {
     fn visit_id(&self, node_id: NodeId);
 }
 
+/// A visitor that applies its operation to all of the node IDs
+/// in a visitable thing.
+
 pub struct IdVisitor<'a, O> {
     pub operation: &'a O,
     pub pass_through_items: bool,
@@ -740,6 +742,38 @@ pub fn static_has_significant_address(mutbl: ast::Mutability,
     inline == InlineNever || inline == InlineNone
 }
 
+
+/// Macro invocations are guaranteed not to occur after expansion is complete.
+/// extracting fields of a method requires a dynamic check to make sure that it's
+/// not a macro invocation, though this check is guaranteed to succeed, assuming
+/// that the invocations are indeed gone.
+macro_rules! method_field_extractor {
+    ($fn_name:ident, $field_ty:ty, $field_pat:pat, $result:ident) => {
+        /// Returns the ident of a Method. To be used after expansion is complete
+        pub fn $fn_name<'a>(method: &'a ast::Method) -> $field_ty {
+            match method.node {
+                $field_pat => $result,
+                MethMac(_) => {
+                    fail!("expected an AST without macro invocations");
+                }
+            }
+        }
+    }
+}
+
+// Note: this is unhygienic in the lifetime 'a. In order to fix this, we'd have to
+// add :lifetime as a macro argument type, so that the 'a could be supplied by the macro
+// invocation.
+pub method_field_extractor!(method_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_),ident)
+pub method_field_extractor!(method_generics,&'a ast::Generics,
+                            MethDecl(_,ref generics,_,_,_,_,_),generics)
+pub method_field_extractor!(method_explicit_self,&'a ast::ExplicitSelf,
+                            MethDecl(_,_,ref explicit_self,_,_,_,_),explicit_self)
+pub method_field_extractor!(method_fn_style,ast::FnStyle,MethDecl(_,_,_,fn_style,_,_,_),fn_style)
+pub method_field_extractor!(method_fn_decl,P<ast::FnDecl>,MethDecl(_,_,_,_,decl,_,_),decl)
+pub method_field_extractor!(method_body,P<ast::Block>,MethDecl(_,_,_,_,_,body,_),body)
+pub method_field_extractor!(method_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,vis),vis)
+
 #[cfg(test)]
 mod test {
     use ast::*;
@@ -765,3 +799,4 @@ mod test {
                 .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice()));
     }
 }
+
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 7d454016d60..46efdccadec 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -648,16 +648,16 @@ impl<'a> MethodDef<'a> {
 
         // Create the method.
         box(GC) ast::Method {
-            ident: method_ident,
             attrs: self.attributes.clone(),
-            generics: fn_generics,
-            explicit_self: explicit_self,
-            fn_style: ast::NormalFn,
-            decl: fn_decl,
-            body: body_block,
             id: ast::DUMMY_NODE_ID,
             span: trait_.span,
-            vis: ast::Inherited,
+            node: ast::MethDecl(method_ident,
+                                fn_generics,
+                                explicit_self,
+                                ast::NormalFn,
+                                fn_decl,
+                                body_block,
+                                ast::Inherited)
         }
     }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 6e44bfa6747..81309181bc0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -941,21 +941,25 @@ impl<'a> Folder for PatIdentRenamer<'a> {
 // expand a method
 fn expand_method(m: &ast::Method, fld: &mut MacroExpander) -> Gc<ast::Method> {
     let id = fld.new_id(m.id);
-    let (rewritten_fn_decl, rewritten_body)
-        = expand_and_rename_fn_decl_and_block(m.decl,m.body,fld);
-
-    // all of the other standard stuff:
     box(GC) ast::Method {
-        id: id,
-        ident: fld.fold_ident(m.ident),
         attrs: m.attrs.iter().map(|a| fld.fold_attribute(*a)).collect(),
-        generics: fold_generics(&m.generics, fld),
-        explicit_self: fld.fold_explicit_self(&m.explicit_self),
-        fn_style: m.fn_style,
-        decl: rewritten_fn_decl,
-        body: rewritten_body,
+        id: id,
         span: fld.new_span(m.span),
-        vis: m.vis
+        node: match m.node {
+            ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
+                let (rewritten_fn_decl, rewritten_body)
+                    = expand_and_rename_fn_decl_and_block(decl,body,fld);
+
+                ast::MethDecl(fld.fold_ident(ident),
+                         fold_generics(generics, fld),
+                         fld.fold_explicit_self(explicit_self),
+                         fn_style,
+                         rewritten_fn_decl,
+                         rewritten_body,
+                         vis)
+            },
+            ast::MethMac(ref _mac) => fail!("expansion in method position not implemented yet!")
+        }
     }
 }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 3e3b57be6e4..88c8318e1b7 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -794,16 +794,21 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
 pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
     let id = folder.new_id(m.id); // Needs to be first, for ast_map.
     box(GC) Method {
-        id: id,
-        ident: folder.fold_ident(m.ident),
         attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
-        generics: fold_generics(&m.generics, folder),
-        explicit_self: folder.fold_explicit_self(&m.explicit_self),
-        fn_style: m.fn_style,
-        decl: folder.fold_fn_decl(&*m.decl),
-        body: folder.fold_block(m.body),
+        id: id,
         span: folder.new_span(m.span),
-        vis: m.vis
+        node: match m.node {
+            MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
+                MethDecl(folder.fold_ident(ident),
+                         fold_generics(generics, folder),
+                         folder.fold_explicit_self(explicit_self),
+                         fn_style,
+                         folder.fold_fn_decl(&*decl),
+                         folder.fold_block(body),
+                         vis)
+            },
+            MethMac(ref mac) => MethMac(folder.fold_mac(mac)),
+        }
     }
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 84db2bc5a22..cc3a7dc095b 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1249,16 +1249,10 @@ impl<'a> Parser<'a> {
                     p.parse_inner_attrs_and_block();
                 let attrs = attrs.append(inner_attrs.as_slice());
                 Provided(box(GC) ast::Method {
-                    ident: ident,
                     attrs: attrs,
-                    generics: generics,
-                    explicit_self: explicit_self,
-                    fn_style: style,
-                    decl: d,
-                    body: body,
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, hi),
-                    vis: vis,
+                    node: ast::MethDecl(ident, generics, explicit_self, style, d, body, vis)
                 })
               }
 
@@ -4049,16 +4043,10 @@ impl<'a> Parser<'a> {
         let hi = body.span.hi;
         let attrs = attrs.append(inner_attrs.as_slice());
         box(GC) ast::Method {
-            ident: ident,
             attrs: attrs,
-            generics: generics,
-            explicit_self: explicit_self,
-            fn_style: fn_style,
-            decl: decl,
-            body: body,
             id: ast::DUMMY_NODE_ID,
             span: mk_sp(lo, hi),
-            vis: visa,
+            node: ast::MethDecl(ident, generics, explicit_self, fn_style, decl, body, visa),
         }
     }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9589a923485..615a4489a73 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -245,6 +245,10 @@ pub fn arg_to_string(arg: &ast::Arg) -> String {
     to_string(|s| s.print_arg(arg))
 }
 
+pub fn mac_to_string(arg: &ast::Mac) -> String {
+    to_string(|s| s.print_mac(arg))
+}
+
 pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
     match vis {
         ast::Public => format!("pub {}", s),
@@ -342,6 +346,7 @@ impl<'a> State<'a> {
         match self.s.last_token() { pp::End => true, _ => false }
     }
 
+    // is this the beginning of a line?
     pub fn is_bol(&mut self) -> bool {
         self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
     }
@@ -627,6 +632,7 @@ impl<'a> State<'a> {
         }
     }
 
+    /// Pretty-print an item
     pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(item.span.lo));
@@ -998,11 +1004,26 @@ impl<'a> State<'a> {
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(meth.span.lo));
         try!(self.print_outer_attributes(meth.attrs.as_slice()));
-        try!(self.print_fn(&*meth.decl, Some(meth.fn_style), abi::Rust,
-                        meth.ident, &meth.generics, Some(meth.explicit_self.node),
-                        meth.vis));
-        try!(word(&mut self.s, " "));
-        self.print_block_with_attrs(&*meth.body, meth.attrs.as_slice())
+        match meth.node {
+            ast::MethDecl(ident, ref generics, ref explicit_self, fn_style, decl, body, vis) => {
+                try!(self.print_fn(&*decl, Some(fn_style), abi::Rust,
+                                   ident, generics, Some(explicit_self.node),
+                                   vis));
+                try!(word(&mut self.s, " "));
+                self.print_block_with_attrs(&*body, meth.attrs.as_slice())
+            },
+            ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
+                                            ..}) => {
+                // code copied from ItemMac:
+                try!(self.print_path(pth, false));
+                try!(word(&mut self.s, "! "));
+                try!(self.cbox(indent_unit));
+                try!(self.popen());
+                try!(self.print_tts(tts.as_slice()));
+                try!(self.pclose());
+                self.end()
+            }
+        }
     }
 
     pub fn print_outer_attributes(&mut self,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7caaf2f6cc1..795f19d0cfb 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -560,15 +560,21 @@ pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V,
 pub fn walk_method_helper<E: Clone, V: Visitor<E>>(visitor: &mut V,
                                                    method: &Method,
                                                    env: E) {
-    visitor.visit_ident(method.span, method.ident, env.clone());
-    visitor.visit_fn(&FkMethod(method.ident, &method.generics, method),
-                     &*method.decl,
-                     &*method.body,
-                     method.span,
-                     method.id,
-                     env.clone());
-    for attr in method.attrs.iter() {
-        visitor.visit_attribute(attr, env.clone());
+    match method.node {
+        MethDecl(ident, ref generics, _, _, decl, body, _) => {
+            visitor.visit_ident(method.span, ident, env.clone());
+            visitor.visit_fn(&FkMethod(ident, generics, method),
+                             decl,
+                             body,
+                             method.span,
+                             method.id,
+                             env.clone());
+            for attr in method.attrs.iter() {
+                visitor.visit_attribute(attr, env.clone());
+            }
+
+        },
+        MethMac(ref mac) => visitor.visit_mac(mac, env.clone())
     }
 }
 
@@ -586,8 +592,12 @@ pub fn walk_fn<E: Clone, V: Visitor<E>>(visitor: &mut V,
         }
         FkMethod(_, generics, method) => {
             visitor.visit_generics(generics, env.clone());
-
-            visitor.visit_explicit_self(&method.explicit_self, env.clone());
+            match method.node {
+                MethDecl(_, _, ref explicit_self, _, _, _, _) =>
+                    visitor.visit_explicit_self(explicit_self, env.clone()),
+                MethMac(ref mac) =>
+                    visitor.visit_mac(mac, env.clone())
+            }
         }
         FkFnBlock(..) => {}
     }