From 9057c8d31023fb682cd7aee7c09d1b3696729b90 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 1 Mar 2017 23:48:16 +0000 Subject: [PATCH] Avoid using `Mark` and `Invocation` for macro defs. --- src/librustc/hir/lowering.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 3 +- src/librustc_resolve/build_reduced_graph.rs | 19 ++--- src/librustc_resolve/lib.rs | 55 ++++++++------ src/librustc_resolve/macros.rs | 79 +++++++++++---------- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/ext/expand.rs | 10 +-- src/libsyntax/ext/hygiene.rs | 7 -- src/libsyntax/ext/tt/macro_rules.rs | 4 +- src/libsyntax/fold.rs | 3 +- src/libsyntax/parse/parser.rs | 3 +- src/libsyntax/print/pprust.rs | 2 +- 13 files changed, 100 insertions(+), 93 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f9f63ccbfde7e..aa6614b0af4f7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1276,7 +1276,7 @@ impl<'a> LoweringContext<'a> { 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 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(), diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index cfe67726ab228..2a67b79eaa52e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -34,7 +34,6 @@ 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}; @@ -420,7 +419,7 @@ impl CrateStore for cstore::CStore { id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs, - node: ast::ItemKind::MacroDef(body.into(), Mark::fresh()), + node: ast::ItemKind::MacroDef(body.into()), vis: ast::Visibility::Inherited, }) } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 8b20c31be03b7..03c61067d64c2 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -492,6 +492,16 @@ impl<'a> Resolver<'a> { }) } + pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> { + let def_id = self.macro_defs[&expansion]; + if let Some(id) = self.definitions.as_local_node_id(def_id) { + self.local_macro_def_scopes[&id] + } else { + let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); + self.get_extern_crate_root(module_def_id.krate) + } + } + pub fn get_macro(&mut self, def: Def) -> Rc { let def_id = match def { Def::Macro(def_id, ..) => def_id, @@ -506,15 +516,6 @@ impl<'a> Resolver<'a> { LoadedMacro::ProcMacro(ext) => return ext, }; - let invocation = self.arenas.alloc_invocation_data(InvocationData { - module: Cell::new(self.get_extern_crate_root(def_id.krate)), - // 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), - }); - 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 diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0f55b53acee26..b19e5f62e275c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -752,8 +752,8 @@ enum RibKind<'a> { // We passed through a module. ModuleRibKind(Module<'a>), - // We passed through a `macro_rules!` statement with the given expansion - MacroDefinition(Mark), + // We passed through a `macro_rules!` statement + MacroDefinition(DefId), // All bindings in this rib are type parameters that can't be used // from the default of a type parameter because they're not declared @@ -970,14 +970,18 @@ impl<'a> NameBinding<'a> { } } - fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc { + fn def_ignoring_ambiguity(&self) -> Def { match self.kind { - NameBindingKind::Import { binding, .. } => binding.get_macro(resolver), - NameBindingKind::Ambiguity { b1, .. } => b1.get_macro(resolver), - _ => resolver.get_macro(self.def()), + NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(), + NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(), + _ => self.def(), } } + fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc { + resolver.get_macro(self.def_ignoring_ambiguity()) + } + // We sometimes need to treat variants as `pub` for backwards compatibility fn pseudo_vis(&self) -> ty::Visibility { if self.is_variant() { ty::Visibility::Public } else { self.vis } @@ -1145,6 +1149,8 @@ pub struct Resolver<'a> { builtin_macros: FxHashMap>, lexical_macro_resolutions: Vec<(Name, &'a Cell>)>, macro_map: FxHashMap>, + macro_defs: FxHashMap, + local_macro_def_scopes: FxHashMap>, macro_exports: Vec, pub whitelisted_legacy_custom_derives: Vec, pub found_unresolved_macro: bool, @@ -1273,6 +1279,9 @@ impl<'a> Resolver<'a> { let features = session.features.borrow(); + let mut macro_defs = FxHashMap(); + macro_defs.insert(Mark::root(), root_def_id); + Resolver { session: session, @@ -1339,6 +1348,8 @@ impl<'a> Resolver<'a> { macro_map: FxHashMap(), macro_exports: Vec::new(), invocations: invocations, + macro_defs: macro_defs, + local_macro_def_scopes: FxHashMap(), name_already_seen: FxHashMap(), whitelisted_legacy_custom_derives: Vec::new(), proc_macro_enabled: features.proc_macro, @@ -1476,12 +1487,12 @@ impl<'a> Resolver<'a> { } } - if let MacroDefinition(mac) = self.ribs[ns][i].kind { + if let MacroDefinition(def) = self.ribs[ns][i].kind { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. - let (source_ctxt, source_macro) = ident.ctxt.source(); - if source_macro == mac { - ident.ctxt = source_ctxt; + let ctxt_data = ident.ctxt.data(); + if def == self.macro_defs[&ctxt_data.outer_mark] { + ident.ctxt = ctxt_data.prev_ctxt; } } } @@ -1489,11 +1500,12 @@ impl<'a> Resolver<'a> { None } - fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a> { - while crate_var_ctxt.source().0 != SyntaxContext::empty() { - crate_var_ctxt = crate_var_ctxt.source().0; + fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext) -> Module<'a> { + let mut ctxt_data = crate_var_ctxt.data(); + while ctxt_data.prev_ctxt != SyntaxContext::empty() { + ctxt_data = ctxt_data.prev_ctxt.data(); } - let module = self.invocations[&crate_var_ctxt.source().1].module.get(); + let module = self.macro_def_scope(ctxt_data.outer_mark); if module.is_local() { self.graph_root } else { module } } @@ -1545,12 +1557,12 @@ impl<'a> Resolver<'a> { NormalRibKind => { // Continue } - MacroDefinition(mac) => { + MacroDefinition(def) => { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. - let (source_ctxt, source_macro) = ident.ctxt.source(); - if source_macro == mac { - ident.ctxt = source_ctxt; + let ctxt_data = ident.ctxt.data(); + if def == self.macro_defs[&ctxt_data.outer_mark] { + ident.ctxt = ctxt_data.prev_ctxt; } } _ => { @@ -1968,10 +1980,11 @@ impl<'a> Resolver<'a> { // Descend into the block. for stmt in &block.stmts { if let ast::StmtKind::Item(ref item) = stmt.node { - if let ast::ItemKind::MacroDef(_, mark) = item.node { + if let ast::ItemKind::MacroDef(..) = item.node { num_macro_definition_ribs += 1; - self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark))); - self.label_ribs.push(Rib::new(MacroDefinition(mark))); + let def = self.definitions.local_def_id(item.id); + self.ribs[ValueNS].push(Rib::new(MacroDefinition(def))); + self.label_ribs.push(Rib::new(MacroDefinition(def))); } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index bec8bf845a75a..7ad122d1c31d8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -74,7 +74,7 @@ pub enum LegacyScope<'a> { pub struct LegacyBinding<'a> { pub parent: Cell>, pub name: ast::Name, - ext: Rc, + def_id: DefId, pub span: Span, } @@ -239,15 +239,34 @@ impl<'a> base::Resolver for Resolver<'a> { fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) -> Result>, Determinacy> { - let (attr, traits, item) = match invoc.kind { + let def = match invoc.kind { InvocationKind::Attr { attr: None, .. } => return Ok(None), + _ => match self.resolve_invoc_to_def(invoc, scope, force) { + Ok(def) => def, + Err(determinacy) => return Err(determinacy), + }, + }; + self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); + Ok(Some(self.get_macro(def))) + } + + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) + -> Result, Determinacy> { + self.resolve_macro_to_def(scope, path, kind, force).map(|def| self.get_macro(def)) + } +} + +impl<'a> Resolver<'a> { + fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) + -> Result { + let (attr, traits, item) = match invoc.kind { InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item), InvocationKind::Bang { ref mac, .. } => { - return self.resolve_macro(scope, &mac.node.path, MacroKind::Bang, force).map(Some); + return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force); } InvocationKind::Derive { name, span, .. } => { let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - return self.resolve_macro(scope, &path, MacroKind::Derive, force).map(Some); + return self.resolve_macro_to_def(scope, &path, MacroKind::Derive, force); } }; @@ -257,8 +276,8 @@ impl<'a> base::Resolver for Resolver<'a> { }; let mut determined = true; - match self.resolve_macro(scope, &path, MacroKind::Attr, force) { - Ok(ext) => return Ok(Some(ext)), + match self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force) { + Ok(def) => return Ok(def), Err(Determinacy::Undetermined) => determined = false, Err(Determinacy::Determined) if force => return Err(Determinacy::Determined), Err(Determinacy::Determined) => {} @@ -293,8 +312,8 @@ impl<'a> base::Resolver for Resolver<'a> { Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined }) } - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) - -> Result, Determinacy> { + fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) + -> Result { let ast::Path { ref segments, span } = *path; if segments.iter().any(|segment| segment.parameters.is_some()) { let kind = @@ -317,10 +336,10 @@ impl<'a> base::Resolver for Resolver<'a> { return Err(Determinacy::Determined); } - let ext = match self.resolve_path(&path, Some(MacroNS), None) { + let def = match self.resolve_path(&path, Some(MacroNS), None) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), - def @ _ => Ok(self.get_macro(def)), + def @ _ => Ok(def), }, PathResult::Module(..) => unreachable!(), PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), @@ -331,15 +350,15 @@ impl<'a> base::Resolver for Resolver<'a> { }; self.current_module.macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); - return ext; + return def; } let name = path[0].name; let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) { - Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()), - Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)), + Some(MacroBinding::Legacy(binding)) => Ok(Def::Macro(binding.def_id, MacroKind::Bang)), + Some(MacroBinding::Modern(binding)) => Ok(binding.def_ignoring_ambiguity()), None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) { - Ok(binding) => Ok(binding.get_macro(self)), + Ok(binding) => Ok(binding.def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -354,9 +373,7 @@ impl<'a> base::Resolver for Resolver<'a> { result } -} -impl<'a> Resolver<'a> { // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`) pub fn resolve_lexical_macro_path_segment(&mut self, ident: Ident, @@ -597,33 +614,23 @@ impl<'a> Resolver<'a> { } pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) { - if item.ident.name == "macro_rules" { + self.local_macro_def_scopes.insert(item.id, self.current_module); + let ident = item.ident; + if ident.name == "macro_rules" { self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`"); } - 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); - } - + let def_id = self.definitions.local_def_id(item.id); + let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, item)); + self.macro_map.insert(def_id, ext); *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding { - parent: Cell::new(*legacy_scope), - name: item.ident.name, - ext: Rc::new(macro_rules::compile(&self.session.parse_sess, item)), - span: item.span, + parent: Cell::new(*legacy_scope), name: ident.name, def_id: def_id, span: item.span, })); - self.macro_names.insert(item.ident.name); + self.macro_names.insert(ident.name); if attr::contains_name(&item.attrs, "macro_export") { - self.macro_exports.push(Export { - name: item.ident.name, - def: Def::Macro(self.definitions.local_def_id(item.id), MacroKind::Bang), - }); + let def = Def::Macro(def_id, MacroKind::Bang); + self.macro_exports.push(Export { name: ident.name, def: def }); } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 35d459422033f..b80de3cc50546 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -211,7 +211,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { LoadedMacro::ProcMacro(..) => continue, }; - let matchers = if let ast::ItemKind::MacroDef(ref tokens, _) = def.node { + 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 { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a79cfc2bceb33..981667337d59a 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::{Mark, SyntaxContext}; +use ext::hygiene::SyntaxContext; use print::pprust; use ptr::P; use symbol::{Symbol, keywords}; @@ -1860,7 +1860,7 @@ pub enum ItemKind { Mac(Mac), /// A macro definition. - MacroDef(ThinTokenStream, Mark /* FIXME(jseyfried) remove this */), + MacroDef(ThinTokenStream), } impl ItemKind { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a208986becf72..96fcea7148bfa 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -154,7 +154,7 @@ impl ExpansionKind { pub struct Invocation { pub kind: InvocationKind, expansion_kind: ExpansionKind, - expansion_data: ExpansionData, + pub expansion_data: ExpansionData, } pub enum InvocationKind { @@ -432,7 +432,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let extname = path.segments.last().unwrap().identifier.name; let ident = ident.unwrap_or(keywords::Invalid.ident()); - let marked_tts = mark_tts(mac.node.stream(), mark); + let marked_tts = + noop_fold_tts(mac.node.stream(), &mut Marker { mark: mark, expn_id: None }); let opt_expanded = match *ext { NormalTT(ref expandfun, exp_span, allow_internal_unstable) => { if ident.name != keywords::Invalid.name() { @@ -1094,8 +1095,3 @@ impl Folder for Marker { span } } - -// apply a given mark to the given token trees. Used prior to expansion of a macro. -pub fn mark_tts(tts: TokenStream, m: Mark) -> TokenStream { - noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None}) -} diff --git a/src/libsyntax/ext/hygiene.rs b/src/libsyntax/ext/hygiene.rs index 83c51bb9d2fcf..57f5ab73d3706 100644 --- a/src/libsyntax/ext/hygiene.rs +++ b/src/libsyntax/ext/hygiene.rs @@ -118,13 +118,6 @@ impl SyntaxContext { }) }) } - - /// If `ident` is macro expanded, return the source ident from the macro definition - /// and the mark of the expansion that created the macro definition. - pub fn source(self) -> (Self /* source context */, Mark /* source macro */) { - let macro_def_ctxt = self.data().prev_ctxt.data(); - (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark) - } } impl fmt::Debug for SyntaxContext { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 8ad679b853e85..7aa1230f9aeea 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, mark_tts}; +use ext::expand::{Expansion, ExpansionKind}; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_failure_msg}; @@ -184,7 +184,7 @@ pub fn compile(sess: &ParseSess, def: &ast::Item) -> SyntaxExtension { // Parse the macro_rules! invocation let body = match def.node { - ast::ItemKind::MacroDef(ref body, mark) => mark_tts(body.clone().into(), mark), + ast::ItemKind::MacroDef(ref body) => body.clone().into(), _ => unreachable!(), }; let argument_map = match parse(sess, body, &argument_gram, None) { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index d23f880bc7bac..fb4eb19be2b15 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -899,8 +899,7 @@ pub fn noop_fold_item_kind(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), + ItemKind::MacroDef(tts) => ItemKind::MacroDef(folder.fold_tts(tts.into()).into()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d81732489dd3d..6446d38e5ef70 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,7 +43,6 @@ 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; @@ -3731,7 +3730,7 @@ impl<'a> Parser<'a> { } let hi = self.prev_span.hi; - let kind = ItemKind::MacroDef(tts, Mark::fresh()); + let kind = ItemKind::MacroDef(tts); Ok(Some(self.mk_item(lo, hi, id, kind, Visibility::Inherited, attrs.to_owned()))) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 78212fb4b447c..3efadbd00d1e0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1328,7 +1328,7 @@ impl<'a> State<'a> { word(&mut self.s, ";")?; self.end()?; } - ast::ItemKind::MacroDef(ref tts, _) => { + ast::ItemKind::MacroDef(ref tts) => { word(&mut self.s, "macro_rules! ")?; self.print_ident(item.ident)?; self.cbox(INDENT_UNIT)?;