]> git.lizzy.rs Git - rust.git/commitdiff
refactor Method definition to make space for macros
authorJohn Clements <clements@racket-lang.org>
Sat, 12 Jul 2014 04:22:11 +0000 (21:22 -0700)
committerJohn Clements <clements@racket-lang.org>
Sun, 13 Jul 2014 17:08:27 +0000 (10:08 -0700)
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.

25 files changed:
src/librustc/metadata/encoder.rs
src/librustc/middle/astencode.rs
src/librustc/middle/dead.rs
src/librustc/middle/effect.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve.rs
src/librustc/middle/save/mod.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/inline.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/error_reporting.rs
src/librustdoc/clean/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/expand.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs

index 493fd575a8408e06fff2c6d8d3400c8361aa099b..6cb0ab51ca10d074f3e09a39f8131777a9434588 100644 (file)
@@ -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 add_to_index(item: &Item, ebml_w: &Encoder,
                     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));
                 }
             }
 
index fb2b4951ea3d68f62d45b2e86e9c293b45605eb2..8fa7d7c2aaa775003de3887e1fe299010a9590d4 100644 (file)
@@ -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: {}::{}",
index 9ec167ee8263ef7d9db5f036d3c67e6142e22d93..d84c62f744edc21b4c49f1be1c03ce6f1ba6d4fc 100644 (file)
@@ -22,6 +22,7 @@
 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 @@ fn visit_node(&mut self, node: &ast_map::Node) {
                 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 @@ fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
     // 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(_) => ()
         }
     }
index 782a380e23a0ecdd3aa98e2f5cbb1adf858d941d..415135a2d048f04ff4bb8ec38207b35fa03d7279 100644 (file)
@@ -17,6 +17,7 @@
 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 @@ fn visit_fn(&mut self, fn_kind: &visit::FnKind, fn_decl: &ast::FnDecl,
             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),
         };
 
index 7630321bd559b0bbc5cd4b8b3b57e21e88bfa6db..580e7b2db57c294a772070b04eba0189916541db 100644 (file)
@@ -26,6 +26,7 @@
 
 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 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
 
                 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 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
                     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 @@ fn check_sane_privacy(&self, item: &ast::Item) {
                                 "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 @@ fn check_sane_privacy(&self, item: &ast::Item) {
                 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 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
         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 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
                     match *m {
                         ast::Required(..) => {}
                         ast::Provided(ref m) => check_inherited(tcx, m.span,
-                                                                m.vis),
+                                                                ast_util::method_vis(&**m)),
                     }
                 }
             }
@@ -1344,7 +1345,7 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
                     // 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, ());
index 26bb0b62cb05fbb1b8869c1bf4e34ad8057b3ba8..d9324574da73f78a4afd9de153ac5c026831c1b3 100644 (file)
@@ -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 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
                 }
             }
             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 @@ fn propagate_node(&mut self, node: &ast_map::Node,
                         // 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
index 4655507f5d1a755c0544e557aeff5b8049acfa4d..6c6ac81b985303ba6b3dd38eb8a67bf8841953e5 100644 (file)
@@ -22,6 +22,7 @@
 
 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 @@ fn build_reduced_graph_for_item(&mut self,
                         // 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 @@ fn build_reduced_graph_for_item(&mut self,
                                 }
                             };
 
-                            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 @@ fn resolve_struct(&mut self,
     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 @@ fn resolve_implementation(&mut self,
     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);
index d16e2bbf66b937ff57a33236813c1de91cdee6e6..a492b4ab9525e193ef67e9dced2af4aa342d8db7 100644 (file)
@@ -333,7 +333,7 @@ fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
             },
         };
 
-        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 @@ fn process_method(&mut self, method: &ast::Method, e:DxrVisitorEnv) {
                             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,
index 9acd04871999aecf94f0dd2ee4e1e4467ee618ff..e3af8f93eadb3590ea50dc40d2ee9a32be786736 100644 (file)
@@ -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)
                 }
index 2ebbc2f5340b79a1cbcc602fce831da84cb9e9b8..f11577482b6dca9ceb3178a171047c53e5a4428b 100644 (file)
@@ -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)
index c79e435707aee724f203f140db71e1d7eac1c3d2..6b54556bbe0ac82644dd25adc68b60d532d9d9cc 100644 (file)
@@ -38,7 +38,7 @@
 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
             }
index 82dfd29320589ac046eedba399b00c2f0159f269..01544214ccf7ff51d3f4592e74984a8ad04c86df 100644 (file)
@@ -25,6 +25,7 @@
 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
                 }
                 _ => {
index cdf434f4099dc831ab493330caace47c54738a92..fb29baeea73f2c592d5ad99303d1e3865863b82d 100644 (file)
@@ -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);
index b6cdeb92aa3a3eed8ab15b28d7c76a96adf1195e..9f08dc2c924839df6f62db371a154ca097300d08 100644 (file)
@@ -57,7 +57,8 @@
 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 ty_of_method(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,
index b0c9900be909cc2bb8ee0d3b2d38e6737a5826f1..bdd6d96f394a29131e357e47eeb9adf6aff022c7 100644 (file)
@@ -693,15 +693,18 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) {
             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 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) {
                                     = 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
index a5c6725bd819c484cded2d9707d243662c8847e6..2e3bb2eef7d9df7b77f14a9f1895854ad0bcc5d9 100644 (file)
@@ -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,
             }),
         }
index dd8304014433a5acdaf5a50c1e31f27869cbfb2c..98318312d58da9884e2ba14ced892813df13a378 100644 (file)
@@ -633,6 +633,8 @@ pub enum Matcher_ {
 /// 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)]
index de2ecd9a2640488fcf3db7c4d6aa67423498448b..d0a0c4fe380f04621b09e8b705c9c2765a914a64 100644 (file)
@@ -304,8 +304,10 @@ pub fn expect_foreign_item(&self, id: NodeId) -> Gc<ForeignItem> {
         }
     }
 
+    /// 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 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem {
                 }
             }
             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 @@ fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -
         }
     }
 
+    /// 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={})",
index cd38c9b3e98c1aa22bbf75c52eeef7cae6f47fb2..a18d8a81ef47f7655b9cfb55a99d9656374ae54c 100644 (file)
@@ -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 @@ fn ident_to_segment(id : &Ident) -> PathSegment {
                 .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice()));
     }
 }
+
index 7d454016d602d3f118adec1126dfba0e1e7e85cc..46efdccadec8033d16b185da5a534b31dd8a316e 100644 (file)
@@ -648,16 +648,16 @@ fn create_method(&self,
 
         // 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)
         }
     }
 
index 6e44bfa6747eb405eef00f66feee6cda5769a073..81309181bc01f35c8de3838813ffc3aebb3ad069 100644 (file)
@@ -941,21 +941,25 @@ fn fold_mac(&mut self, macro: &ast::Mac) -> ast::Mac {
 // 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!")
+        }
     }
 }
 
index 3e3b57be6e40650ff77c14ed99fc93d30aa37317..88c8318e1b78bd31051d84ec6a4d5ca05dd9441a 100644 (file)
@@ -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)),
+        }
     }
 }
 
index 84db2bc5a2217cf6ba00c09ce2529ab355070d3b..cc3a7dc095bd25136e3b1ab9ed890a2661d5b627 100644 (file)
@@ -1249,16 +1249,10 @@ pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
                     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 @@ fn parse_method(&mut self,
         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),
         }
     }
 
index 9589a92348585c2f32168e342dd30b9467e8a10f..615a4489a73de46041e29694a90db51b2776e962 100644 (file)
@@ -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 @@ pub fn is_end(&mut self) -> bool {
         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 @@ pub fn print_foreign_item(&mut self,
         }
     }
 
+    /// 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 @@ pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> {
         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,
index 7caaf2f6cc1faccee1c1b98ab774e3b08ef17e1f..795f19d0cfb06170050fea6da1206a8e09390189 100644 (file)
@@ -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(..) => {}
     }