diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2017-03-05 05:15:58 +0000 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2017-03-10 08:08:32 -0800 |
| commit | 212b6c25507b963b60a646a2ff3df7496bd30acf (patch) | |
| tree | 8fd7c3e2317c5b9c92e17aaec9b4c48a72f75ac7 /src | |
| parent | f573db4f80c75f156df8a743f456bf087ec81dc2 (diff) | |
| download | rust-212b6c25507b963b60a646a2ff3df7496bd30acf.tar.gz rust-212b6c25507b963b60a646a2ff3df7496bd30acf.zip | |
Refactor out `ast::ItemKind::MacroDef`.
Diffstat (limited to 'src')
25 files changed, 172 insertions, 196 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 257cdb960d5..f9f63ccbfde 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { 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 @@ impl<'a> LoweringContext<'a> { bounds, items) } - ItemKind::Mac(_) => panic!("Shouldn't still be around"), + ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"), } } @@ -1256,42 +1258,45 @@ impl<'a> LoweringContext<'a> { } } - 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 { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index ccaf663c7ad..f15e063e81e 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -108,7 +108,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { 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 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { 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), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4a7027b8997..e9fb4632fa1 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -136,7 +136,7 @@ pub struct NativeLibrary { } pub enum LoadedMacro { - MacroRules(ast::MacroDef), + MacroDef(ast::Item), ProcMacro(Rc<SyntaxExtension>), } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9619ba84724..e458d45bbd6 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -43,7 +43,6 @@ use super::Compilation; 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, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index cf2219e0e3d..cfe67726ab2 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -34,6 +34,7 @@ use std::rc::Rc; 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 @@ impl CrateStore for cstore::CStore { 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, }) } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 65a60732fc8..749146fe496 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -375,9 +375,4 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { 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) - } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index da08d1b7c78..8b20c31be03 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -37,7 +37,6 @@ use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; 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 @@ impl<'a> Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { 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, ¯o_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, ¯o_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), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d51ec268ec2..9ea129c2efb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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 @@ impl<'a> Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { // `#![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 @@ impl<'a> Resolver<'a> { } } - ItemKind::ExternCrate(_) => { + ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => { // do nothing, these are just around to be encoded } @@ -2031,9 +2024,9 @@ impl<'a> Resolver<'a> { // 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))); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 720d616e007..fc6b1baca16 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -25,7 +25,7 @@ use syntax::errors::DiagnosticBuilder; 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::fold::{self, Folder}; 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 @@ impl<'a> base::Resolver for Resolver<'a> { 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 @@ impl<'a> base::Resolver for Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { } 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); } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 42928427233..35d45942203 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -16,6 +16,7 @@ use std::mem; 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } 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(), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9cc754cbf4d..a79cfc2bceb 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,7 +20,7 @@ pub use util::ThinVec; 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 @@ impl ItemKind { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::Mac(..) | + ItemKind::MacroDef(..) | ItemKind::Impl(..) | ItemKind::DefaultImpl(..) => "item" } @@ -1912,24 +1915,6 @@ impl ForeignItemKind { } } -/// 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; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e242cf2777f..39d91910614 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -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 @@ impl Resolver for DummyResolver { 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 } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f1662284a88..8451414ec3d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -948,17 +948,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { 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 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } 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 { diff --git a/src/libsyntax/ext/hygiene.rs b/src/libsyntax/ext/hygiene.rs index 2af5c2ea999..83c51bb9d2f 100644 --- a/src/libsyntax/ext/hygiene.rs +++ b/src/libsyntax/ext/hygiene.rs @@ -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 { diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index e2fb1946e90..f60b1d17a5e 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -21,7 +21,6 @@ use util::move_map::MoveMap; 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 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> { 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 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> { _ => {} } - 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) }); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 1d386c1a3ac..8ad679b853e 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -12,7 +12,7 @@ use {ast, attr}; 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); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4242b0f8b98..d23f880bc7b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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 @@ mod tests { 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()); } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6c566dab1d6..d81732489dd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,6 +43,7 @@ use {ast, attr}; 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 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { }) } - 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 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { attrs: self.parse_inner_attributes()?, module: self.parse_mod_items(&token::Eof, lo)?, span: mk_sp(lo, self.span.lo), - exported_macros: Vec::new(), }) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 53ef8e8dfa4..78212fb4b44 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1318,7 +1318,6 @@ impl<'a> State<'a> { 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 @@ impl<'a> State<'a> { 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)) } diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index b90802d1e7e..9d9957a0f45 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -148,9 +148,4 @@ impl<'ast> Visitor<'ast> for NodeCounter { 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) - } - } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 013632141de..ee7dd18247b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -125,9 +125,6 @@ pub trait Visitor<'ast>: Sized { 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, ¯o_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); } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 3bceb02f3d6..b51591bf89d 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -99,7 +99,7 @@ macro_rules! derive_traits { 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)) ); diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index f92cde4019f..1e9b112b6df 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -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 { diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 9c96ad547e1..5adaf470f23 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -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 @@ impl<'a> CollectProcMacros<'a> { 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. // diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs index 0717af98b30..3d2dd380e48 100644 --- a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs @@ -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 */ } |
