]> git.lizzy.rs Git - rust.git/commitdiff
Refactor out `ast::ItemKind::MacroDef`.
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Sun, 5 Mar 2017 05:15:58 +0000 (05:15 +0000)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 10 Mar 2017 16:08:32 +0000 (08:08 -0800)
25 files changed:
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/middle/cstore.rs
src/librustc_driver/driver.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_passes/hir_stats.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustdoc/visit_ast.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/hygiene.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/node_count.rs
src/libsyntax/visit.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/test/run-make/pretty-expanded-hygiene/input.pp.rs

index 257cdb960d5293ba3e9c4fd4b7a1a21270916915..f9f63ccbfde7e8d9eb6109e516fa9b2e031af9c8 100644 (file)
@@ -79,6 +79,7 @@ pub struct LoweringContext<'a> {
     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
     bodies: BTreeMap<hir::BodyId, hir::Body>,
+    exported_macros: Vec<hir::MacroDef>,
 
     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
     trait_default_impl: BTreeMap<DefId, NodeId>,
@@ -121,6 +122,7 @@ pub fn lower_crate(sess: &Session,
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         trait_default_impl: BTreeMap::new(),
+        exported_macros: Vec::new(),
         loop_scopes: Vec::new(),
         is_in_loop_condition: false,
         type_def_lifetime_params: DefIdMap(),
@@ -170,9 +172,10 @@ struct ItemLowerer<'lcx, 'interner: 'lcx> {
 
         impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
             fn visit_item(&mut self, item: &'lcx Item) {
-                let hir_item = self.lctx.lower_item(item);
-                self.lctx.items.insert(item.id, hir_item);
-                visit::walk_item(self, item);
+                if let Some(hir_item) = self.lctx.lower_item(item) {
+                    self.lctx.items.insert(item.id, hir_item);
+                    visit::walk_item(self, item);
+                }
             }
 
             fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
@@ -195,14 +198,13 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
 
         let module = self.lower_mod(&c.module);
         let attrs = self.lower_attrs(&c.attrs);
-        let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
         let body_ids = body_ids(&self.bodies);
 
         hir::Crate {
             module: module,
             attrs: attrs,
             span: c.span,
-            exported_macros: exported_macros,
+            exported_macros: hir::HirVec::from(self.exported_macros),
             items: self.items,
             trait_items: self.trait_items,
             impl_items: self.impl_items,
@@ -1134,7 +1136,7 @@ fn lower_item_kind(&mut self,
                                bounds,
                                items)
             }
-            ItemKind::Mac(_) => panic!("Shouldn't still be around"),
+            ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
         }
     }
 
@@ -1256,42 +1258,45 @@ fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         }
     }
 
-    fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
-        hir::MacroDef {
-            name: m.ident.name,
-            attrs: self.lower_attrs(&m.attrs),
-            id: m.id,
-            span: m.span,
-            body: m.body.clone().into(),
-        }
-    }
-
     fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
-        if let ItemKind::Use(ref view_path) = i.node {
-            if let ViewPathList(_, ref imports) = view_path.node {
-                return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
-                    .map(|id| hir::ItemId { id: id }).collect();
+        match i.node {
+            ItemKind::Use(ref view_path) => {
+                if let ViewPathList(_, ref imports) = view_path.node {
+                    return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
+                        .map(|id| hir::ItemId { id: id }).collect();
+                }
             }
+            ItemKind::MacroDef(..) => return SmallVector::new(),
+            _ => {}
         }
         SmallVector::one(hir::ItemId { id: i.id })
     }
 
-    pub fn lower_item(&mut self, i: &Item) -> hir::Item {
+    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
         let mut name = i.ident.name;
         let attrs = self.lower_attrs(&i.attrs);
         let mut vis = self.lower_visibility(&i.vis);
+        if let ItemKind::MacroDef(ref tts, _) = i.node {
+            if i.attrs.iter().any(|attr| attr.name() == "macro_export") {
+                self.exported_macros.push(hir::MacroDef {
+                    name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
+                });
+            }
+            return None;
+        }
+
         let node = self.with_parent_def(i.id, |this| {
             this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
         });
 
-        hir::Item {
+        Some(hir::Item {
             id: i.id,
             name: name,
             attrs: attrs,
             node: node,
             vis: vis,
             span: i.span,
-        }
+        })
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
index ccaf663c7ad2ab03a844ca80e107b9a2e8c2719f..f15e063e81e337ce6e53e9df924fc67a234ebf4e 100644 (file)
@@ -108,7 +108,7 @@ fn visit_item(&mut self, i: &'a Item) {
             ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
                 DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::Use(ref view_path) => {
                 match view_path.node {
@@ -269,10 +269,6 @@ fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
         self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'a MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str()));
-    }
-
     fn visit_stmt(&mut self, stmt: &'a Stmt) {
         match stmt.node {
             StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
index 4a7027b8997a5854befdef64121af1d4b96a373e..e9fb4632fa178c4cb6029adb0faae13aecd2d718 100644 (file)
@@ -136,7 +136,7 @@ pub struct NativeLibrary {
 }
 
 pub enum LoadedMacro {
-    MacroRules(ast::MacroDef),
+    MacroDef(ast::Item),
     ProcMacro(Rc<SyntaxExtension>),
 }
 
index 9619ba8472404bb70e0a1fffca1e620841dbe528..e458d45bbd6e8cdd6a4ca1b19f356756b38afe80 100644 (file)
@@ -43,7 +43,6 @@
 use serialize::json;
 
 use std::env;
-use std::mem;
 use std::ffi::{OsString, OsStr};
 use std::fs;
 use std::io::{self, Write};
@@ -705,8 +704,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         krate
     });
 
-    krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new());
-
     krate = time(time_passes, "maybe building test harness", || {
         syntax::test::modify_for_testing(&sess.parse_sess,
                                          &mut resolver,
index cf2219e0e3df51c5aaf58764232b247be88e0882..cfe67726ab2285af3b4cfd48ccfc5f92c38619bd 100644 (file)
@@ -34,6 +34,7 @@
 
 use syntax::ast;
 use syntax::attr;
+use syntax::ext::hygiene::Mark;
 use syntax::parse::filemap_to_stream;
 use syntax::symbol::Symbol;
 use syntax_pos::{mk_sp, Span};
@@ -414,12 +415,13 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
         sess.imported_macro_spans.borrow_mut()
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
-        LoadedMacro::MacroRules(ast::MacroDef {
+        LoadedMacro::MacroDef(ast::Item {
             ident: ast::Ident::with_empty_ctxt(name),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs,
-            body: body.into(),
+            node: ast::ItemKind::MacroDef(body.into(), Mark::fresh()),
+            vis: ast::Visibility::Inherited,
         })
     }
 
index 65a60732fc8074e423790ba73597b0e387316d64..749146fe49672a766c755e2fd02b180fbadf57cc 100644 (file)
@@ -375,9 +375,4 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v ast::TypeBinding) {
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
         self.record("Attribute", Id::None, attr);
     }
-
-    fn visit_macro_def(&mut self, macro_def: &'v ast::MacroDef) {
-        self.record("MacroDef", Id::None, macro_def);
-        ast_visit::walk_macro_def(self, macro_def)
-    }
 }
index da08d1b7c78e2d1edf302f74bf26fb05a4e820ae..8b20c31be03b7dac692eaa2c54f5ec73f32d2c57 100644 (file)
@@ -37,7 +37,6 @@
 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::Undetermined;
-use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::parse::token;
@@ -373,7 +372,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.current_module = module;
             }
-            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
+            ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
         }
     }
 
@@ -502,22 +501,21 @@ pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
             return ext.clone();
         }
 
-        let mut macro_rules = match self.session.cstore.load_macro(def_id, &self.session) {
-            LoadedMacro::MacroRules(macro_rules) => macro_rules,
+        let macro_def = match self.session.cstore.load_macro(def_id, &self.session) {
+            LoadedMacro::MacroDef(macro_def) => macro_def,
             LoadedMacro::ProcMacro(ext) => return ext,
         };
 
-        let mark = Mark::fresh();
         let invocation = self.arenas.alloc_invocation_data(InvocationData {
             module: Cell::new(self.get_extern_crate_root(def_id.krate)),
-            def_index: CRATE_DEF_INDEX,
-            const_expr: false,
-            legacy_scope: Cell::new(LegacyScope::Empty),
-            expansion: Cell::new(LegacyScope::Empty),
+            // FIXME(jseyfried) the following are irrelevant
+            def_index: CRATE_DEF_INDEX, const_expr: false,
+            legacy_scope: Cell::new(LegacyScope::Empty), expansion: Cell::new(LegacyScope::Empty),
         });
-        self.invocations.insert(mark, invocation);
-        macro_rules.body = mark_tts(macro_rules.stream(), mark).into();
-        let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, &macro_rules));
+        if let ast::ItemKind::MacroDef(_, mark) = macro_def.node {
+            self.invocations.insert(mark, invocation);
+        }
+        let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, &macro_def));
         self.macro_map.insert(def_id, ext.clone());
         ext
     }
@@ -707,12 +705,12 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_item(&mut self, item: &'a Item) {
         let macro_use = match item.node {
-            ItemKind::Mac(ref mac) => {
-                if mac.node.path.segments.is_empty() {
-                    self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
-                } else {
-                    self.resolver.define_macro(item, &mut self.legacy_scope);
-                }
+            ItemKind::MacroDef(..) => {
+                self.resolver.define_macro(item, &mut self.legacy_scope);
+                return
+            }
+            ItemKind::Mac(..) => {
+                self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
                 return
             }
             ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
index d51ec268ec21788a19d972452343b4449af0c13d..9ea129c2efbf695f5c9c8a6fb61896afe15af6f7 100644 (file)
@@ -1092,10 +1092,6 @@ pub struct Resolver<'a> {
 
     pub definitions: Definitions,
 
-    // Maps the node id of a statement to the expansions of the `macro_rules!`s
-    // immediately above the statement (if appropriate).
-    macros_at_scope: FxHashMap<NodeId, Vec<Mark>>,
-
     graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
@@ -1171,7 +1167,6 @@ pub struct Resolver<'a> {
     dummy_binding: &'a NameBinding<'a>,
     use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
 
-    pub exported_macros: Vec<ast::MacroDef>,
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Name>,
     builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
@@ -1309,7 +1304,6 @@ pub fn new(session: &'a Session,
             session: session,
 
             definitions: definitions,
-            macros_at_scope: FxHashMap(),
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
@@ -1365,7 +1359,6 @@ pub fn new(session: &'a Session,
             // `#![feature(proc_macro)]` implies `#[feature(extern_macros)]`
             use_extern_macros: features.use_extern_macros || features.proc_macro,
 
-            exported_macros: Vec::new(),
             crate_loader: crate_loader,
             macro_names: FxHashSet(),
             builtin_macros: FxHashMap(),
@@ -1696,7 +1689,7 @@ fn resolve_item(&mut self, item: &Item) {
                 }
             }
 
-            ItemKind::ExternCrate(_) => {
+            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
                 // do nothing, these are just around to be encoded
             }
 
@@ -2031,9 +2024,9 @@ fn resolve_block(&mut self, block: &Block) {
 
         // Descend into the block.
         for stmt in &block.stmts {
-            if let Some(marks) = self.macros_at_scope.remove(&stmt.id) {
-                num_macro_definition_ribs += marks.len() as u32;
-                for mark in marks {
+            if let ast::StmtKind::Item(ref item) = stmt.node {
+                if let ast::ItemKind::MacroDef(_, mark) = item.node {
+                    num_macro_definition_ribs += 1;
                     self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark)));
                     self.label_ribs.push(Rib::new(MacroDefinition(mark)));
                 }
index 720d616e007d21ea5f6fc1d974756ea744bbca4e..fc6b1baca160b7f0fbc0c5161ad1d2d0b7803d8a 100644 (file)
@@ -25,7 +25,7 @@
 use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
 use syntax::ext::base::MacroKind;
-use syntax::ext::expand::{Expansion, mark_tts};
+use syntax::ext::expand::Expansion;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{self, emit_feature_err, GateIssue};
@@ -33,7 +33,6 @@
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::visit::Visitor;
 use syntax_pos::{Span, DUMMY_SP};
 
 #[derive(Clone)]
@@ -151,7 +150,7 @@ fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark
         invocation.expansion.set(visitor.legacy_scope);
     }
 
-    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
+    fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         let def_id = DefId {
             krate: BUILTIN_MACROS_CRATE,
             index: DefIndex::new(self.macro_map.len()),
@@ -167,10 +166,6 @@ fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         self.builtin_macros.insert(ident.name, binding);
     }
 
-    fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) {
-        self.macros_at_scope.insert(id, macros);
-    }
-
     fn resolve_imports(&mut self) {
         ImportResolver { resolver: self }.resolve_imports()
     }
@@ -544,45 +539,33 @@ fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Ex
     }
 
     pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
-        let tts = match item.node {
-            ast::ItemKind::Mac(ref mac) => mac.node.stream(),
-            _ => unreachable!(),
-        };
-
         if item.ident.name == "macro_rules" {
             self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
         }
 
-        let mark = Mark::from_placeholder_id(item.id);
-        let invocation = self.invocations[&mark];
-        invocation.module.set(self.current_module);
-
-        let mut def = ast::MacroDef {
-            ident: item.ident,
-            attrs: item.attrs.clone(),
-            id: ast::DUMMY_NODE_ID,
-            span: item.span,
-            body: mark_tts(tts, mark).into(),
-        };
+        let invocation = self.arenas.alloc_invocation_data(InvocationData {
+            module: Cell::new(self.current_module),
+            // FIXME(jseyfried) the following are irrelevant
+            def_index: CRATE_DEF_INDEX, const_integer: false,
+            legacy_scope: Cell::new(LegacyScope::Empty), expansion: Cell::new(LegacyScope::Empty),
+        });
+        if let ast::ItemKind::MacroDef(_, mark) = item.node {
+            self.invocations.insert(mark, invocation);
+        }
 
         *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
             parent: Cell::new(*legacy_scope),
-            name: def.ident.name,
-            ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
-            span: def.span,
+            name: item.ident.name,
+            ext: Rc::new(macro_rules::compile(&self.session.parse_sess, item)),
+            span: item.span,
         }));
-        self.macro_names.insert(def.ident.name);
+        self.macro_names.insert(item.ident.name);
 
-        if attr::contains_name(&def.attrs, "macro_export") {
-            def.id = self.next_node_id();
-            DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
-                collector.visit_macro_def(&def)
-            });
+        if attr::contains_name(&item.attrs, "macro_export") {
             self.macro_exports.push(Export {
-                name: def.ident.name,
-                def: Def::Macro(self.definitions.local_def_id(def.id), MacroKind::Bang),
+                name: item.ident.name,
+                def: Def::Macro(self.definitions.local_def_id(item.id), MacroKind::Bang),
             });
-            self.exported_macros.push(def);
         }
     }
 
index 42928427233d780723a0996911e96dabfe6446e3..35d459422033fb687a07b8d5bb7ff9264c9d3580 100644 (file)
@@ -16,6 +16,7 @@
 use syntax::abi;
 use syntax::ast;
 use syntax::attr;
+use syntax::tokenstream::TokenStream;
 use syntax_pos::Span;
 
 use rustc::hir::map as hir_map;
@@ -205,14 +206,17 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
                     }
                     let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
                     let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
-                        LoadedMacro::MacroRules(macro_rules) => macro_rules,
+                        LoadedMacro::MacroDef(macro_def) => macro_def,
                         // FIXME(jseyfried): document proc macro reexports
                         LoadedMacro::ProcMacro(..) => continue,
                     };
 
-                    // FIXME(jseyfried) merge with `self.visit_macro()`
-                    let tts = def.stream().trees().collect::<Vec<_>>();
-                    let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
+                    let matchers = if let ast::ItemKind::MacroDef(ref tokens, _) = def.node {
+                        let tts: Vec<_> = TokenStream::from(tokens.clone()).into_trees().collect();
+                        tts.chunks(4).map(|arm| arm[0].span()).collect()
+                    } else {
+                        unreachable!()
+                    };
                     om.macros.push(Macro {
                         def_id: def_id,
                         attrs: def.attrs.clone().into(),
index 9cc754cbf4d1912590251b479d80716f69f35f68..a79cfc2bceb33d467a43841ee47dab7d98f3885e 100644 (file)
@@ -20,7 +20,7 @@
 use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId};
 use codemap::{respan, Spanned};
 use abi::Abi;
-use ext::hygiene::SyntaxContext;
+use ext::hygiene::{Mark, SyntaxContext};
 use print::pprust;
 use ptr::P;
 use symbol::{Symbol, keywords};
@@ -414,7 +414,6 @@ pub struct Crate {
     pub module: Mod,
     pub attrs: Vec<Attribute>,
     pub span: Span,
-    pub exported_macros: Vec<MacroDef>,
 }
 
 /// A spanned compile-time attribute list item.
@@ -1855,10 +1854,13 @@ pub enum ItemKind {
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
              Vec<ImplItem>),
-    /// A macro invocation (which includes macro definition).
+    /// A macro invocation.
     ///
     /// E.g. `macro_rules! foo { .. }` or `foo!(..)`
     Mac(Mac),
+
+    /// A macro definition.
+    MacroDef(ThinTokenStream, Mark /* FIXME(jseyfried) remove this */),
 }
 
 impl ItemKind {
@@ -1877,6 +1879,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::Mac(..) |
+            ItemKind::MacroDef(..) |
             ItemKind::Impl(..) |
             ItemKind::DefaultImpl(..) => "item"
         }
@@ -1912,24 +1915,6 @@ pub fn descriptive_variant(&self) -> &str {
     }
 }
 
-/// A macro definition, in this crate or imported from another.
-///
-/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct MacroDef {
-    pub ident: Ident,
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub body: ThinTokenStream,
-}
-
-impl MacroDef {
-    pub fn stream(&self) -> TokenStream {
-        self.body.clone().into()
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use serialize;
index e242cf2777fe59dd00fbed82820a06848bb39c82..39d919106147dda7e9a8943bf9869af23f19ddc3 100644 (file)
@@ -552,8 +552,7 @@ pub trait Resolver {
     fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
-    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
-    fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
+    fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
 
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
@@ -577,8 +576,7 @@ fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
     fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
-    fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
-    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
+    fn add_builtin(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
index f1662284a88206657283952e9c444e4c5ea39397..8451414ec3d8a7b13d3c6796c890451c92af402e 100644 (file)
@@ -948,17 +948,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         match item.node {
             ast::ItemKind::Mac(..) => {
                 self.check_attributes(&item.attrs);
-                let is_macro_def = if let ItemKind::Mac(ref mac) = item.node {
-                    mac.node.path.segments[0].identifier.name == "macro_rules"
-                } else {
-                    unreachable!()
-                };
-
-                item.and_then(|mut item| match item.node {
-                    ItemKind::Mac(_) if is_macro_def => {
-                        item.id = Mark::fresh().as_placeholder_id();
-                        SmallVector::one(P(item))
-                    }
+                item.and_then(|item| match item.node {
                     ItemKind::Mac(mac) => {
                         self.collect(ExpansionKind::Items, InvocationKind::Bang {
                             mac: mac,
@@ -1078,7 +1068,10 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
     }
 
     fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
-        noop_fold_item_kind(self.cfg.configure_item_kind(item), self)
+        match item {
+            ast::ItemKind::MacroDef(..) => item,
+            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
+        }
     }
 
     fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
index 2af5c2ea9995ef61f20ba390f2efffd5bf043065..83c51bb9d2fcfaf1f42d808da9156bed3e0794d6 100644 (file)
@@ -31,7 +31,7 @@ pub struct SyntaxContextData {
 }
 
 /// A mark is a unique id associated with a macro expansion.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)]
 pub struct Mark(u32);
 
 impl Mark {
index e2fb1946e90dbdd05b1299e1a6d6c33dae3a2882..f60b1d17a5e2f0c3c74058602712b3d172b35148 100644 (file)
@@ -21,7 +21,6 @@
 use util::small_vector::SmallVector;
 
 use std::collections::HashMap;
-use std::mem;
 
 pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
     fn mac_placeholder() -> ast::Mac {
@@ -174,20 +173,11 @@ fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
 
     fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
         noop_fold_block(block, self).map(|mut block| {
-            let mut macros = Vec::new();
             let mut remaining_stmts = block.stmts.len();
 
             block.stmts = block.stmts.move_flat_map(|mut stmt| {
                 remaining_stmts -= 1;
 
-                // `macro_rules!` macro definition
-                if let ast::StmtKind::Item(ref item) = stmt.node {
-                    if let ast::ItemKind::Mac(_) = item.node {
-                        macros.push(Mark::from_placeholder_id(item.id));
-                        return None;
-                    }
-                }
-
                 match stmt.node {
                     // Avoid wasting a node id on a trailing expression statement,
                     // which shares a HIR node with the expression itself.
@@ -201,11 +191,6 @@ fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
                     _ => {}
                 }
 
-                if self.monotonic && !macros.is_empty() {
-                    let macros = mem::replace(&mut macros, Vec::new());
-                    self.cx.resolver.add_expansions_at_stmt(stmt.id, macros);
-                }
-
                 Some(stmt)
             });
 
index 1d386c1a3ac930f494630fcefc44039feb0be40b..8ad679b853e856cfea72177546d97d96fdfb2dd0 100644 (file)
@@ -12,7 +12,7 @@
 use syntax_pos::{Span, DUMMY_SP};
 use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
 use ext::base::{NormalTT, TTMacroExpander};
-use ext::expand::{Expansion, ExpansionKind};
+use ext::expand::{Expansion, ExpansionKind, mark_tts};
 use ext::tt::macro_parser::{Success, Error, Failure};
 use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
 use ext::tt::macro_parser::{parse, parse_failure_msg};
@@ -153,7 +153,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
 // Holy self-referential!
 
 /// Converts a `macro_rules!` invocation into a syntax extension.
-pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
+pub fn compile(sess: &ParseSess, def: &ast::Item) -> SyntaxExtension {
     let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs"));
     let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs"));
 
@@ -183,7 +183,11 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
     ];
 
     // Parse the macro_rules! invocation
-    let argument_map = match parse(sess, def.body.clone().into(), &argument_gram, None) {
+    let body = match def.node {
+        ast::ItemKind::MacroDef(ref body, mark) => mark_tts(body.clone().into(), mark),
+        _ => unreachable!(),
+    };
+    let argument_map = match parse(sess, body, &argument_gram, None) {
         Success(m) => m,
         Failure(sp, tok) => {
             let s = parse_failure_msg(tok);
index 4242b0f8b9803d17df7b06e2c18b55987a1ce671..d23f880bc7bac6901623a3bd9f0b9b946302bdae 100644 (file)
@@ -899,6 +899,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             items.move_flat_map(|item| folder.fold_trait_item(item)),
         ),
         ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)),
+        ItemKind::MacroDef(tts, mark) => ItemKind::MacroDef(folder.fold_tts(tts.into()).into(),
+                                                            mark),
     }
 }
 
@@ -959,7 +961,7 @@ pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod
     }
 }
 
-pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, mut exported_macros, span}: Crate,
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
                                   folder: &mut T) -> Crate {
     let mut items = folder.fold_item(P(ast::Item {
         ident: keywords::Invalid.ident(),
@@ -987,14 +989,9 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, mut exported_macros, spa
         }, vec![], span)
     };
 
-    for def in &mut exported_macros {
-        def.id = folder.new_id(def.id);
-    }
-
     Crate {
         module: module,
         attrs: attrs,
-        exported_macros: exported_macros,
         span: span,
     }
 }
@@ -1387,6 +1384,6 @@ macro_rules! assert_pred {
             matches_codepattern,
             "matches_codepattern",
             pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
-            "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
+            "macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
     }
 }
index 6c566dab1d6060df69321913816289568062f3f7..d81732489dd3d68b909e5d199c3d77909a1335bf 100644 (file)
@@ -43,6 +43,7 @@
 use codemap::{self, CodeMap, Spanned, spanned, respan};
 use syntax_pos::{self, Span, Pos, BytePos, mk_sp};
 use errors::{self, DiagnosticBuilder};
+use ext::hygiene::Mark;
 use parse::{self, classify, token};
 use parse::common::SeqSep;
 use parse::lexer::TokenAndSpan;
@@ -1048,7 +1049,7 @@ pub fn bump_with(&mut self,
         self.expected_tokens.clear();
     }
 
-    pub fn look_ahead<R, F>(&mut self, dist: usize, f: F) -> R where
+    pub fn look_ahead<R, F>(&self, dist: usize, f: F) -> R where
         F: FnOnce(&token::Token) -> R,
     {
         if dist == 0 {
@@ -3699,11 +3700,41 @@ fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
         })
     }
 
-    fn is_union_item(&mut self) -> bool {
+    fn is_union_item(&self) -> bool {
         self.token.is_keyword(keywords::Union) &&
         self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
     }
 
+    fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility)
+                     -> PResult<'a, Option<P<Item>>> {
+        let lo = self.span.lo;
+        match self.token {
+            token::Ident(ident) if ident.name == "macro_rules" => {
+                if self.look_ahead(1, |t| *t == token::Not) {
+                    let prev_span = self.prev_span;
+                    self.complain_if_pub_macro(vis, prev_span);
+                    self.bump();
+                    self.bump();
+                }
+            }
+            _ => return Ok(None),
+        };
+
+        let id = self.parse_ident()?;
+        let (delim, tts) = self.expect_delimited_token_tree()?;
+        if delim != token::Brace {
+            if !self.eat(&token::Semi) {
+                let msg = "macros that expand to items must either be surrounded with braces \
+                           or followed by a semicolon";
+                self.span_err(self.prev_span, msg);
+            }
+        }
+
+        let hi = self.prev_span.hi;
+        let kind = ItemKind::MacroDef(tts, Mark::fresh());
+        Ok(Some(self.mk_item(lo, hi, id, kind, Visibility::Inherited, attrs.to_owned())))
+    }
+
     fn parse_stmt_without_recovery(&mut self,
                                    macro_legacy_warnings: bool)
                                    -> PResult<'a, Option<Stmt>> {
@@ -3718,6 +3749,12 @@ fn parse_stmt_without_recovery(&mut self,
                 node: StmtKind::Local(self.parse_local(attrs.into())?),
                 span: mk_sp(lo, self.prev_span.hi),
             }
+        } else if let Some(macro_def) = self.eat_macro_def(&attrs, &Visibility::Inherited)? {
+            Stmt {
+                id: ast::DUMMY_NODE_ID,
+                node: StmtKind::Item(macro_def),
+                span: mk_sp(lo, self.prev_span.hi),
+            }
         // Starts like a simple path, but not a union item.
         } else if self.token.is_path_start() &&
                   !self.token.is_qpath_start() &&
@@ -5767,6 +5804,10 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
+        if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility)? {
+            return Ok(Some(macro_def));
+        }
+
         self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility)
     }
 
@@ -5948,7 +5989,6 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
             attrs: self.parse_inner_attributes()?,
             module: self.parse_mod_items(&token::Eof, lo)?,
             span: mk_sp(lo, self.span.lo),
-            exported_macros: Vec::new(),
         })
     }
 
index 53ef8e8dfa49c3c225a8abfacd59827f6c1da906..78212fb4b447cfec4afd5f5fa4a1a413ce4d3c5c 100644 (file)
@@ -1318,7 +1318,6 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.bclose(item.span)?;
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
-                self.print_visibility(&item.vis)?;
                 self.print_path(&node.path, false, 0, false)?;
                 word(&mut self.s, "! ")?;
                 self.print_ident(item.ident)?;
@@ -1329,6 +1328,16 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 word(&mut self.s, ";")?;
                 self.end()?;
             }
+            ast::ItemKind::MacroDef(ref tts, _) => {
+                word(&mut self.s, "macro_rules! ")?;
+                self.print_ident(item.ident)?;
+                self.cbox(INDENT_UNIT)?;
+                self.popen()?;
+                self.print_tts(tts.clone().into())?;
+                self.pclose()?;
+                word(&mut self.s, ";")?;
+                self.end()?;
+            }
         }
         self.ann.post(self, NodeItem(item))
     }
index b90802d1e7eb8f908b5a5de1ac6957789712c7db..9d9957a0f45341c06746f44d886b842b1caa0c28 100644 (file)
@@ -148,9 +148,4 @@ fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
     fn visit_attribute(&mut self, _attr: &Attribute) {
         self.count += 1;
     }
-    fn visit_macro_def(&mut self, macro_def: &MacroDef) {
-        self.count += 1;
-        walk_macro_def(self, macro_def)
-    }
-
 }
index 013632141dee69b27baf174a1abfe5a62b9fb973..ee7dd18247b213d4b6b6a7c153b8db3c74ca3d60 100644 (file)
@@ -125,9 +125,6 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
         walk_assoc_type_binding(self, type_binding)
     }
     fn visit_attribute(&mut self, _attr: &'ast Attribute) {}
-    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
-        walk_macro_def(self, macro_def)
-    }
     fn visit_vis(&mut self, vis: &'ast Visibility) {
         walk_vis(self, vis)
     }
@@ -176,12 +173,6 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident)
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
     visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
     walk_list!(visitor, visit_attribute, &krate.attrs);
-    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
-}
-
-pub fn walk_macro_def<'a, V: Visitor<'a>>(visitor: &mut V, macro_def: &'a MacroDef) {
-    visitor.visit_ident(macro_def.span, macro_def.ident);
-    walk_list!(visitor, visit_attribute, &macro_def.attrs);
 }
 
 pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) {
@@ -295,6 +286,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_trait_item, methods);
         }
         ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ItemKind::MacroDef(..) => {},
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
 }
index 3bceb02f3d6c5af6a2e2cff0a5cb9c452ce275c5..b51591bf89d5e2275724a87d7a41c6d82dcb72c6 100644 (file)
@@ -99,7 +99,7 @@ pub fn is_builtin_trait(name: ast::Name) -> bool {
 
         pub fn register_builtin_derives(resolver: &mut Resolver) {
             $(
-                resolver.add_ext(
+                resolver.add_builtin(
                     ast::Ident::with_empty_ctxt(Symbol::intern($name)),
                     Rc::new(SyntaxExtension::BuiltinDerive($func))
                 );
index f92cde4019f67b06e9147c6264badd7e4e41cfac..1e9b112b6df564263738be5f058d2e4c1a54bed6 100644 (file)
@@ -59,7 +59,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
     deriving::register_builtin_derives(resolver);
 
     let mut register = |name, ext| {
-        resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
+        resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };
 
     macro_rules! register {
index 9c96ad547e1ae33254dc8034826b68748db50bc9..5adaf470f2374be020e1e2b0330ad3d87cd99762 100644 (file)
@@ -90,12 +90,7 @@ pub fn modify(sess: &ParseSess,
 
     krate.module.items.push(mk_registrar(&mut cx, &derives, &attr_macros, &bang_macros));
 
-    if krate.exported_macros.len() > 0 {
-        handler.err("cannot export macro_rules! macros from a `proc-macro` \
-                     crate type currently");
-    }
-
-    return krate
+    krate
 }
 
 fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
@@ -251,6 +246,15 @@ fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, attr: &'a ast::Attrib
 
 impl<'a> Visitor<'a> for CollectProcMacros<'a> {
     fn visit_item(&mut self, item: &'a ast::Item) {
+        if let ast::ItemKind::MacroDef(..) = item.node {
+            if self.is_proc_macro_crate &&
+               item.attrs.iter().any(|attr| attr.name() == "macro_export") {
+                let msg =
+                    "cannot export macro_rules! macros from a `proc-macro` crate type currently";
+                self.handler.span_err(item.span, msg);
+            }
+        }
+
         // First up, make sure we're checking a bare function. If we're not then
         // we're just not interested in this item.
         //
index 0717af98b30b43c87600cdecba73241d1056b4a4..3d2dd380e488e76abadd2afed8c68435b56f4909 100644 (file)
@@ -12,6 +12,7 @@
 #![feature(no_core)]
 #![no_core]
 
+macro_rules! foo /* 60#0 */(( $ x : ident ) => { y + $ x });
 
 fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }