Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
resolve: Eliminate InvocationData
It was very similar to `ParentScope` and mostly could be replaced by it.
  • Loading branch information
petrochenkov committed Aug 15, 2019
commit 59dd07ae2bbc8d6c46bdb5f3d5b93a6729848311
23 changes: 10 additions & 13 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Here we build the "reduced graph": the graph of the module tree without
//! any imports resolved.

use crate::macros::{InvocationData, LegacyBinding, LegacyScope};
use crate::macros::{LegacyBinding, LegacyScope};
use crate::resolve_imports::ImportDirective;
use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
Expand Down Expand Up @@ -1063,20 +1063,17 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
false
}

fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> {
fn visit_invoc(&mut self, id: ast::NodeId) -> LegacyScope<'a> {
let invoc_id = id.placeholder_to_expn_id();

self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id);
let parent_scope = self.parent_scope.clone();
parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id);

let invocation_data = self.r.arenas.alloc_invocation_data(InvocationData {
module: self.parent_scope.module,
parent_legacy_scope: self.parent_scope.legacy,
output_legacy_scope: Cell::new(None),
});
let old_invocation_data = self.r.invocations.insert(invoc_id, invocation_data);
assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation");
let old_parent_scope =
self.r.invocation_parent_scopes.insert(invoc_id, parent_scope.clone());
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");

invocation_data
LegacyScope::Invocation(invoc_id)
}

fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
Expand Down Expand Up @@ -1177,7 +1174,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
return
}
ItemKind::Mac(..) => {
self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(item.id));
self.parent_scope.legacy = self.visit_invoc(item.id);
return
}
ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
Expand All @@ -1196,7 +1193,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {

fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
if let ast::StmtKind::Mac(..) = stmt.node {
self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id));
self.parent_scope.legacy = self.visit_invoc(stmt.id);
} else {
visit::walk_stmt(self, stmt);
}
Expand Down
29 changes: 14 additions & 15 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ use diagnostics::{Suggestion, ImportSuggestion};
use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
use late::{PathSource, Rib, RibKind::*};
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
use macros::{InvocationData, LegacyBinding, LegacyScope};
use macros::{LegacyBinding, LegacyScope};

type Res = def::Res<NodeId>;

Expand Down Expand Up @@ -911,9 +911,12 @@ pub struct Resolver<'a> {
/// FIXME: Find a way for `PartialEq` and `Eq` to emulate `#[structural_match]`
/// by marking the produced impls rather than the original items.
special_derives: FxHashMap<ExpnId, SpecialDerives>,

/// Maps the `ExpnId` of an expansion to its containing module or block.
invocations: FxHashMap<ExpnId, &'a InvocationData<'a>>,
/// Parent scopes in which the macros were invoked.
/// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
/// Legacy scopes *produced* by expanding the macro invocations,
/// include all the `macro_rules` items and other invocations generated by them.
output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>,

/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,
Expand All @@ -936,7 +939,6 @@ pub struct ResolverArenas<'a> {
name_bindings: arena::TypedArena<NameBinding<'a>>,
import_directives: arena::TypedArena<ImportDirective<'a>>,
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
invocation_data: arena::TypedArena<InvocationData<'a>>,
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
}

Expand All @@ -961,10 +963,6 @@ impl<'a> ResolverArenas<'a> {
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default())
}
fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>)
-> &'a InvocationData<'a> {
self.invocation_data.alloc(expansion_data)
}
fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> {
self.legacy_bindings.alloc(binding)
}
Expand Down Expand Up @@ -1078,9 +1076,8 @@ impl<'a> Resolver<'a> {
}
}

let mut invocations = FxHashMap::default();
invocations.insert(ExpnId::root(),
arenas.alloc_invocation_data(InvocationData::default(graph_root)));
let mut invocation_parent_scopes = FxHashMap::default();
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::default(graph_root));

let mut macro_defs = FxHashMap::default();
macro_defs.insert(ExpnId::root(), root_def_id);
Expand Down Expand Up @@ -1152,7 +1149,8 @@ impl<'a> Resolver<'a> {
dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
invocations,
invocation_parent_scopes,
output_legacy_scopes: Default::default(),
macro_defs,
local_macro_def_scopes: FxHashMap::default(),
name_already_seen: FxHashMap::default(),
Expand Down Expand Up @@ -1370,8 +1368,9 @@ impl<'a> Resolver<'a> {
LegacyScope::Binding(binding) => Scope::MacroRules(
binding.parent_legacy_scope
),
LegacyScope::Invocation(invoc) => Scope::MacroRules(
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
LegacyScope::Invocation(invoc_id) => Scope::MacroRules(
self.output_legacy_scopes.get(&invoc_id).cloned()
.unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy)
),
LegacyScope::Empty => Scope::Module(module),
}
Expand Down
92 changes: 29 additions & 63 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
use crate::{ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
use crate::Namespace::*;
use crate::build_reduced_graph::BuildReducedGraphVisitor;
Expand All @@ -22,36 +22,11 @@ use syntax::feature_gate::GateIssue;
use syntax::symbol::{Symbol, kw, sym};
use syntax_pos::{Span, DUMMY_SP};

use std::cell::Cell;
use std::{mem, ptr};
use rustc_data_structures::sync::Lrc;

type Res = def::Res<ast::NodeId>;

// FIXME: Merge this with `ParentScope`.
#[derive(Clone, Debug)]
pub struct InvocationData<'a> {
/// The module in which the macro was invoked.
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: 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.
crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>,
}

impl<'a> InvocationData<'a> {
pub fn default(module: Module<'a>) -> Self {
InvocationData {
module,
parent_legacy_scope: LegacyScope::Empty,
output_legacy_scope: Cell::new(None),
}
}
}

/// Binding produced by a `macro_rules` item.
/// Not modularized, can shadow previous legacy bindings, etc.
#[derive(Debug)]
Expand All @@ -75,7 +50,7 @@ pub enum LegacyScope<'a> {
Binding(&'a LegacyBinding<'a>),
/// The scope introduced by a macro invocation that can potentially
/// create a `macro_rules!` macro definition.
Invocation(&'a InvocationData<'a>),
Invocation(ExpnId),
}

// Macro namespace is separated into two sub-namespaces, one for bang macros and
Expand Down Expand Up @@ -124,9 +99,8 @@ impl<'a> base::Resolver for Resolver<'a> {
ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
)));
let module = self.module_map[&self.definitions.local_def_id(id)];
let invocation_data = self.arenas.alloc_invocation_data(InvocationData::default(module));
self.invocation_parent_scopes.insert(expn_id, ParentScope::default(module));
self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index);
self.invocations.insert(expn_id, invocation_data);
expn_id
}

Expand All @@ -140,29 +114,29 @@ impl<'a> base::Resolver for Resolver<'a> {
});
}

fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment,
derives: &[ExpnId]) {
fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expn_id));

let invocation = self.invocations[&expn_id];
invocation.module.unresolved_invocations.borrow_mut().remove(&expn_id);
invocation.module.unresolved_invocations.borrow_mut().extend(derives);
let parent_def = self.definitions.invocation_parent(expn_id);
fn visit_ast_fragment_with_placeholders(
&mut self, expansion: ExpnId, fragment: &AstFragment, derives: &[ExpnId]
) {
// Fill in some data for derives if the fragment is from a derive container.
let parent_scope = self.invocation_parent_scopes[&expansion].clone();
let parent_def = self.definitions.invocation_parent(expansion);
self.invocation_parent_scopes.extend(
derives.iter().map(|&derive| (derive, parent_scope.clone()))
);
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 {
r: self,
parent_scope: ParentScope {
module: invocation.module,
expansion: expn_id,
legacy: invocation.parent_legacy_scope,
derives: Vec::new(),
},
};
parent_scope.module.unresolved_invocations.borrow_mut().remove(&expansion);
parent_scope.module.unresolved_invocations.borrow_mut().extend(derives);

// Integrate the new AST fragment into all the definition and module structures.
// We are inside the `expansion` new, but other parent scope components are still the same.
fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expansion));
let parent_scope = ParentScope { expansion, ..parent_scope };
let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
fragment.visit_with(&mut visitor);
invocation.output_legacy_scope.set(Some(visitor.parent_scope.legacy));
let output_legacy_scope = visitor.parent_scope.legacy;
self.output_legacy_scopes.insert(expansion, output_legacy_scope);
}

fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
Expand All @@ -178,7 +152,8 @@ impl<'a> base::Resolver for Resolver<'a> {

fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
let parent_scope = &self.invocation_parent_scopes[&invoc_id].clone();
let (path, kind, derives, after_derive) = match invoc.kind {
InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
(&attr.path, MacroKind::Attr, derives.clone(), after_derive),
InvocationKind::Bang { ref mac, .. } =>
Expand All @@ -192,7 +167,6 @@ impl<'a> base::Resolver for Resolver<'a> {
// will automatically knows about itself.
let mut result = Ok(None);
if derives.len() > 1 {
let parent_scope = &self.invoc_parent_scope(invoc_id, Vec::new());
for path in derives {
match self.resolve_macro_path(path, Some(MacroKind::Derive),
parent_scope, true, force) {
Expand All @@ -209,7 +183,8 @@ impl<'a> base::Resolver for Resolver<'a> {
}
};

let parent_scope = &self.invoc_parent_scope(invoc_id, derives_in_scope);
// Derives are not included when `invocations` are collected, so we have to add them here.
let parent_scope = &ParentScope { derives, ..parent_scope.clone() };
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;

let span = invoc.span();
Expand Down Expand Up @@ -247,16 +222,6 @@ impl<'a> base::Resolver for Resolver<'a> {
}

impl<'a> Resolver<'a> {
fn invoc_parent_scope(&self, invoc_id: ExpnId, derives: Vec<ast::Path>) -> ParentScope<'a> {
let invoc = self.invocations[&invoc_id];
ParentScope {
module: invoc.module,
expansion: invoc_id.parent(),
legacy: invoc.parent_legacy_scope,
derives,
}
}

/// Resolve macro path with error reporting and recovery.
fn smart_resolve_macro_path(
&mut self,
Expand Down Expand Up @@ -466,8 +431,9 @@ impl<'a> Resolver<'a> {
Scope::MacroRules(legacy_scope) => match legacy_scope {
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
Ok((legacy_binding.binding, Flags::MACRO_RULES)),
LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() =>
Err(Determinacy::Undetermined),
LegacyScope::Invocation(invoc_id)
if !this.output_legacy_scopes.contains_key(&invoc_id) =>
Err(Determinacy::Undetermined),
_ => Err(Determinacy::Determined),
}
Scope::CrateRoot => {
Expand Down