macro_names: FnvHashSet<Name>,
// Maps the `Mark` of an expansion to its containing module or block.
- expansion_data: Vec<macros::ExpansionData>,
+ expansion_data: FnvHashMap<u32, macros::ExpansionData>,
}
pub struct ResolverArenas<'a> {
let mut module_map = NodeMap();
module_map.insert(CRATE_NODE_ID, graph_root);
+ let mut expansion_data = FnvHashMap();
+ expansion_data.insert(0, macros::ExpansionData::default()); // Crate root expansion
+
Resolver {
session: session,
macro_loader: macro_loader,
macro_names: FnvHashSet(),
- expansion_data: vec![macros::ExpansionData::default()],
+ expansion_data: expansion_data,
}
}
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
expansion.visit_with(&mut ExpansionVisitor {
- current_module: self.expansion_data[mark.as_u32() as usize].module.clone(),
+ current_module: self.expansion_data[&mark.as_u32()].module.clone(),
resolver: self,
});
}
self.macro_names.insert(ident.name);
}
- let mut module = self.expansion_data[scope.as_u32() as usize].module.clone();
+ let mut module = self.expansion_data[&scope.as_u32()].module.clone();
while module.macros_escape {
module = module.parent.clone().unwrap();
}
fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
for i in 0..attrs.len() {
let name = intern(&attrs[i].name());
- match self.expansion_data[0].module.macros.borrow().get(&name) {
+ match self.expansion_data[&0].module.macros.borrow().get(&name) {
Some(ext) => match **ext {
MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
_ => {}
None
}
- fn resolve_invoc(&mut self, invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
+ fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
let (name, span) = match invoc.kind {
InvocationKind::Bang { ref mac, .. } => {
let path = &mac.node.path;
InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span),
};
- let mut module = self.expansion_data[invoc.mark().as_u32() as usize].module.clone();
+ let mut module = self.expansion_data[&scope.as_u32()].module.clone();
loop {
if let Some(ext) = module.macros.borrow().get(&name) {
return Some(ext.clone());
impl<'a, 'b> ExpansionVisitor<'a, 'b> {
fn visit_invoc(&mut self, id: ast::NodeId) {
- assert_eq!(id.as_u32(), self.resolver.expansion_data.len() as u32);
- self.resolver.expansion_data.push(ExpansionData {
+ self.resolver.expansion_data.insert(id.as_u32(), ExpansionData {
module: self.current_module.clone(),
});
}
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
- fn resolve_invoc(&mut self, invoc: &Invocation) -> Option<Rc<SyntaxExtension>>;
+ fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>>;
}
pub enum LoadedMacro {
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
- fn resolve_invoc(&mut self, _invoc: &Invocation) -> Option<Rc<SyntaxExtension>> { None }
+ fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
+ None
+ }
}
#[derive(Clone)]
InvocationKind::Attr { ref attr, .. } => attr.span,
}
}
-
- pub fn mark(&self) -> Mark {
- self.expansion_data.mark
- }
}
pub struct MacroExpander<'a, 'b:'a> {
let ExpansionData { depth, mark, .. } = invoc.expansion_data;
self.cx.current_expansion = invoc.expansion_data.clone();
- let expansion = match self.cx.resolver.resolve_invoc(&invoc) {
+ let scope = if self.monotonic { mark } else { orig_expansion_data.mark };
+ self.cx.current_expansion.mark = scope;
+ let expansion = match self.cx.resolver.resolve_invoc(scope, &invoc) {
Some(ext) => self.expand_invoc(invoc, ext),
None => invoc.expansion_kind.dummy(invoc.span()),
};
};
self.cx.cfg = crate_config;
- let mark = self.cx.current_expansion.mark;
- self.cx.resolver.visit_expansion(mark, &result.0);
+ if self.monotonic {
+ let mark = self.cx.current_expansion.mark;
+ self.cx.resolver.visit_expansion(mark, &result.0);
+ }
+
result
}
/// Expand a macro invocation. Returns the result of expansion.
fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
- let (mark, kind) = (invoc.mark(), invoc.expansion_kind);
+ let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
let (attrs, mac, ident, span) = match invoc.kind {
InvocationKind::Bang { attrs, mac, ident, span } => (attrs, mac, ident, span),
_ => unreachable!(),