use crate::hir::map::definitions::*;
-use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex};
-use crate::session::CrateDisambiguator;
+use crate::hir::def_id::DefIndex;
use syntax::ast::*;
use syntax::ext::hygiene::Mark;
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
expansion: Mark,
- pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>,
-}
-
-pub struct MacroInvocationData {
- pub mark: Mark,
- pub def_index: DefIndex,
}
impl<'a> DefCollector<'a> {
pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
- DefCollector {
- definitions,
- expansion,
- parent_def: None,
- visit_macro_invoc: None,
- }
- }
-
- pub fn collect_root(&mut self,
- crate_name: &str,
- crate_disambiguator: CrateDisambiguator) {
- let root = self.definitions.create_root_def(crate_name,
- crate_disambiguator);
- assert_eq!(root, CRATE_DEF_INDEX);
- self.parent_def = Some(root);
+ let parent_def = Some(definitions.invocation_parent(expansion));
+ DefCollector { definitions, parent_def, expansion }
}
fn create_def(&mut self,
}
fn visit_macro_invoc(&mut self, id: NodeId) {
- if let Some(ref mut visit) = self.visit_macro_invoc {
- visit(MacroInvocationData {
- mark: id.placeholder_to_mark(),
- def_index: self.parent_def.unwrap(),
- })
- }
+ self.definitions.set_invocation_parent(id.placeholder_to_mark(), self.parent_def.unwrap());
}
}
expansions_that_defined: FxHashMap<DefIndex, Mark>,
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
def_index_to_span: FxHashMap<DefIndex, Span>,
+ /// When collecting definitions from an AST fragment produced by a macro invocation `Mark`
+ /// we know what parent node that fragment should be attached to thanks to this table.
+ invocation_parents: FxHashMap<Mark, DefIndex>,
}
/// A unique identifier that we can use to lookup a definition
assert!(self.def_index_to_node.is_empty());
self.def_index_to_node.push(ast::CRATE_NODE_ID);
self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
+ self.set_invocation_parent(Mark::root(), root_index);
// Allocate some other DefIndices that always must exist.
GlobalMetaDataKind::allocate_def_indices(self);
pub fn add_parent_module_of_macro_def(&mut self, mark: Mark, module: DefId) {
self.parent_modules_of_macro_defs.insert(mark, module);
}
+
+ pub fn invocation_parent(&self, invoc_id: Mark) -> DefIndex {
+ self.invocation_parents[&invoc_id]
+ }
+
+ pub fn set_invocation_parent(&mut self, invoc_id: Mark, parent: DefIndex) {
+ let old_parent = self.invocation_parents.insert(invoc_id, parent);
+ assert!(old_parent.is_none(), "parent def-index is reset for an invocation");
+ }
}
impl DefPathData {
use crate::resolve_imports::ImportResolver;
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc::hir::map::{self, DefCollector};
+use rustc::hir::map::DefCollector;
use rustc::middle::stability;
use rustc::{ty, lint, span_bug};
use syntax::ast::{self, Ident};
type Res = def::Res<ast::NodeId>;
+// FIXME: Merge this with `ParentScope`.
#[derive(Clone, Debug)]
pub struct InvocationData<'a> {
- def_index: DefIndex,
/// The module in which the macro was invoked.
- crate module: Cell<Module<'a>>,
+ crate module: Module<'a>,
/// The legacy scope in which the macro was invoked.
/// The invocation path is resolved in this scope.
- crate parent_legacy_scope: Cell<LegacyScope<'a>>,
+ crate parent_legacy_scope: LegacyScope<'a>,
/// The legacy scope *produced* by expanding this macro invocation,
/// includes all the macro_rules items, other invocations, etc generated by it.
/// `None` if the macro is not expanded yet.
impl<'a> InvocationData<'a> {
pub fn root(graph_root: Module<'a>) -> Self {
InvocationData {
- module: Cell::new(graph_root),
- def_index: CRATE_DEF_INDEX,
- parent_legacy_scope: Cell::new(LegacyScope::Empty),
- output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
+ module: graph_root,
+ parent_legacy_scope: LegacyScope::Empty,
+ output_legacy_scope: Cell::new(None),
}
}
}
/// can potentially expand into macro definitions.
#[derive(Copy, Clone, Debug)]
pub enum LegacyScope<'a> {
- /// Created when invocation data is allocated in the arena;
- /// must be replaced with a proper scope later.
- Uninitialized,
/// Empty "root" scope at the crate start containing no names.
Empty,
/// The scope introduced by a `macro_rules!` macro definition.
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
let mark = Mark::fresh(Mark::root());
let module = self.module_map[&self.definitions.local_def_id(id)];
+ self.definitions.set_invocation_parent(mark, module.def_id().unwrap().index);
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
- module: Cell::new(module),
- def_index: module.def_id().unwrap().index,
- parent_legacy_scope: Cell::new(LegacyScope::Empty),
- output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
+ module,
+ parent_legacy_scope: LegacyScope::Empty,
+ output_legacy_scope: Cell::new(None),
}));
mark
}
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]) {
- let invocation = self.invocations[&mark];
- self.collect_def_ids(mark, invocation, fragment);
+ fragment.visit_with(&mut DefCollector::new(&mut self.definitions, mark));
- self.current_module = invocation.module.get();
+ let invocation = self.invocations[&mark];
+ self.current_module = invocation.module;
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
+ let parent_def = self.definitions.invocation_parent(mark);
+ for &derive_invoc_id in derives {
+ self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
+ }
self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
let mut visitor = BuildReducedGraphVisitor {
resolver: self,
- current_legacy_scope: invocation.parent_legacy_scope.get(),
+ current_legacy_scope: invocation.parent_legacy_scope,
expansion: mark,
};
fragment.visit_with(&mut visitor);
fn invoc_parent_scope(&self, invoc_id: Mark, derives: Vec<ast::Path>) -> ParentScope<'a> {
let invoc = self.invocations[&invoc_id];
ParentScope {
- module: invoc.module.get().nearest_item_scope(),
+ module: invoc.module.nearest_item_scope(),
expansion: invoc_id.parent(),
- legacy: invoc.parent_legacy_scope.get(),
+ legacy: invoc.parent_legacy_scope,
derives,
}
}
binding.parent_legacy_scope
),
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
- invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
+ invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
),
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
- LegacyScope::Uninitialized => unreachable!(),
}
WhereToResolve::CrateRoot => match ns {
TypeNS => {
}
}
- fn collect_def_ids(&mut self,
- mark: Mark,
- invocation: &'a InvocationData<'a>,
- fragment: &AstFragment) {
- let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
- let InvocationData { def_index, .. } = *invocation;
-
- let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
- invocations.entry(invoc.mark).or_insert_with(|| {
- arenas.alloc_invocation_data(InvocationData {
- def_index: invoc.def_index,
- module: Cell::new(graph_root),
- parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
- output_legacy_scope: Cell::new(None),
- })
- });
- };
-
- let mut def_collector = DefCollector::new(&mut self.definitions, mark);
- def_collector.visit_macro_invoc = Some(visit_macro_invoc);
- def_collector.with_parent(def_index, |def_collector| {
- fragment.visit_with(def_collector)
- });
- }
-
crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.