Avoid using Mark and Invocation for macro defs.

This commit is contained in:
Jeffrey Seyfried 2017-03-01 23:48:16 +00:00 committed by Alex Crichton
parent e839486318
commit 8c98996934
13 changed files with 100 additions and 93 deletions

View file

@ -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(),

View file

@ -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,
})
}

View file

@ -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<SyntaxExtension> {
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, &macro_def));
self.macro_map.insert(def_id, ext.clone());
ext

View file

@ -779,8 +779,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
@ -997,14 +997,18 @@ impl<'a> NameBinding<'a> {
}
}
fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc<SyntaxExtension> {
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<SyntaxExtension> {
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 }
@ -1172,6 +1176,8 @@ pub struct Resolver<'a> {
builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
macro_exports: Vec<Export>,
pub whitelisted_legacy_custom_derives: Vec<Name>,
pub found_unresolved_macro: bool,
@ -1300,6 +1306,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,
@ -1366,6 +1375,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,
@ -1503,12 +1514,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;
}
}
}
@ -1516,11 +1527,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 }
}
@ -1572,12 +1584,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;
}
}
_ => {
@ -2025,10 +2037,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)));
}
}

View file

@ -74,7 +74,7 @@ pub enum LegacyScope<'a> {
pub struct LegacyBinding<'a> {
pub parent: Cell<LegacyScope<'a>>,
pub name: ast::Name,
ext: Rc<SyntaxExtension>,
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<Option<Rc<SyntaxExtension>>, 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<Rc<SyntaxExtension>, 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<Def, Determinacy> {
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<Rc<SyntaxExtension>, Determinacy> {
fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-> Result<Def, Determinacy> {
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 });
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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})
}

View file

@ -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 {

View file

@ -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) {

View file

@ -899,8 +899,7 @@ 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),
ItemKind::MacroDef(tts) => ItemKind::MacroDef(folder.fold_tts(tts.into()).into()),
}
}

View file

@ -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())))
}

View file

@ -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)?;