Skip to content

Commit

Permalink
Avoid using Mark and Invocation for macro defs.
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried committed Mar 7, 2017
1 parent a519659 commit 9057c8d
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 93 deletions.
2 changes: 1 addition & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
})
}
Expand Down
19 changes: 10 additions & 9 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
55 changes: 34 additions & 21 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -970,14 +970,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 }
Expand Down Expand Up @@ -1145,6 +1149,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,
Expand Down Expand Up @@ -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,

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -1476,24 +1487,25 @@ 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;
}
}
}

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

Expand Down Expand Up @@ -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;
}
}
_ => {
Expand Down Expand Up @@ -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)));
}
}

Expand Down
79 changes: 43 additions & 36 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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);
}
};

Expand All @@ -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) => {}
Expand Down Expand Up @@ -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 =
Expand All @@ -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),
Expand All @@ -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(_) => {
Expand All @@ -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,
Expand Down Expand Up @@ -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 });
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -1860,7 +1860,7 @@ pub enum ItemKind {
Mac(Mac),

/// A macro definition.
MacroDef(ThinTokenStream, Mark /* FIXME(jseyfried) remove this */),
MacroDef(ThinTokenStream),
}

impl ItemKind {
Expand Down
10 changes: 3 additions & 7 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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})
}
Loading

0 comments on commit 9057c8d

Please sign in to comment.