resolve: Legacy(Scope,Binding) -> MacroRules(Scope,Binding)

This commit is contained in:
Vadim Petrochenkov 2020-03-14 01:06:36 +03:00
parent 65bf4831d2
commit 3fbb2549ce
4 changed files with 67 additions and 53 deletions

View File

@ -7,7 +7,7 @@
use crate::def_collector::collect_definitions; use crate::def_collector::collect_definitions;
use crate::imports::{Import, ImportKind}; use crate::imports::{Import, ImportKind};
use crate::macros::{LegacyBinding, LegacyScope}; use crate::macros::{MacroRulesBinding, MacroRulesScope};
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError};
use crate::{ use crate::{
@ -165,11 +165,11 @@ impl<'a> Resolver<'a> {
&mut self, &mut self,
fragment: &AstFragment, fragment: &AstFragment,
parent_scope: ParentScope<'a>, parent_scope: ParentScope<'a>,
) -> LegacyScope<'a> { ) -> MacroRulesScope<'a> {
collect_definitions(&mut self.definitions, fragment, parent_scope.expansion); collect_definitions(&mut self.definitions, fragment, parent_scope.expansion);
let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
fragment.visit_with(&mut visitor); fragment.visit_with(&mut visitor);
visitor.parent_scope.legacy visitor.parent_scope.macro_rules
} }
crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
@ -1060,7 +1060,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
false false
} }
fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScope<'a> {
let invoc_id = id.placeholder_to_expn_id(); let invoc_id = id.placeholder_to_expn_id();
self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
@ -1068,7 +1068,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
LegacyScope::Invocation(invoc_id) MacroRulesScope::Invocation(invoc_id)
} }
fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
@ -1095,7 +1095,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
} }
} }
fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> {
let parent_scope = self.parent_scope; let parent_scope = self.parent_scope;
let expansion = parent_scope.expansion; let expansion = parent_scope.expansion;
let (ext, ident, span, macro_rules) = match &item.kind { let (ext, ident, span, macro_rules) = match &item.kind {
@ -1108,7 +1108,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.r.proc_macro_stubs.insert(item.id); self.r.proc_macro_stubs.insert(item.id);
(self.r.dummy_ext(macro_kind), ident, span, false) (self.r.dummy_ext(macro_kind), ident, span, false)
} }
None => return parent_scope.legacy, None => return parent_scope.macro_rules,
}, },
_ => unreachable!(), _ => unreachable!(),
}; };
@ -1137,8 +1137,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.r.check_reserved_macro_name(ident, res); self.r.check_reserved_macro_name(ident, res);
self.insert_unused_macro(ident, item.id, span); self.insert_unused_macro(ident, item.id, span);
} }
LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
parent_legacy_scope: parent_scope.legacy, parent_macro_rules_scope: parent_scope.macro_rules,
binding, binding,
ident, ident,
})) }))
@ -1149,7 +1149,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.insert_unused_macro(ident, item.id, span); self.insert_unused_macro(ident, item.id, span);
} }
self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
self.parent_scope.legacy self.parent_scope.macro_rules
} }
} }
} }
@ -1174,29 +1174,29 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_item(&mut self, item: &'b Item) { fn visit_item(&mut self, item: &'b Item) {
let macro_use = match item.kind { let macro_use = match item.kind {
ItemKind::MacroDef(..) => { ItemKind::MacroDef(..) => {
self.parent_scope.legacy = self.define_macro(item); self.parent_scope.macro_rules = self.define_macro(item);
return; return;
} }
ItemKind::MacCall(..) => { ItemKind::MacCall(..) => {
self.parent_scope.legacy = self.visit_invoc(item.id); self.parent_scope.macro_rules = self.visit_invoc(item.id);
return; return;
} }
ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
_ => false, _ => false,
}; };
let orig_current_module = self.parent_scope.module; let orig_current_module = self.parent_scope.module;
let orig_current_legacy_scope = self.parent_scope.legacy; let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
self.build_reduced_graph_for_item(item); self.build_reduced_graph_for_item(item);
visit::walk_item(self, item); visit::walk_item(self, item);
self.parent_scope.module = orig_current_module; self.parent_scope.module = orig_current_module;
if !macro_use { if !macro_use {
self.parent_scope.legacy = orig_current_legacy_scope; self.parent_scope.macro_rules = orig_current_macro_rules_scope;
} }
} }
fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
if let ast::StmtKind::MacCall(..) = stmt.kind { if let ast::StmtKind::MacCall(..) = stmt.kind {
self.parent_scope.legacy = self.visit_invoc(stmt.id); self.parent_scope.macro_rules = self.visit_invoc(stmt.id);
} else { } else {
visit::walk_stmt(self, stmt); visit::walk_stmt(self, stmt);
} }
@ -1214,11 +1214,11 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_block(&mut self, block: &'b Block) { fn visit_block(&mut self, block: &'b Block) {
let orig_current_module = self.parent_scope.module; let orig_current_module = self.parent_scope.module;
let orig_current_legacy_scope = self.parent_scope.legacy; let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
self.build_reduced_graph_for_block(block); self.build_reduced_graph_for_block(block);
visit::walk_block(self, block); visit::walk_block(self, block);
self.parent_scope.module = orig_current_module; self.parent_scope.module = orig_current_module;
self.parent_scope.legacy = orig_current_legacy_scope; self.parent_scope.macro_rules = orig_current_macro_rules_scope;
} }
fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) {

View File

@ -21,7 +21,9 @@ use rustc_span::{BytePos, MultiSpan, Span};
use crate::imports::{Import, ImportKind, ImportResolver}; use crate::imports::{Import, ImportKind, ImportResolver};
use crate::path_names_to_string; use crate::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; use crate::{
BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot,
};
use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError}; use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment}; use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
@ -498,12 +500,12 @@ impl<'a> Resolver<'a> {
} }
} }
} }
Scope::MacroRules(legacy_scope) => { Scope::MacroRules(macro_rules_scope) => {
if let LegacyScope::Binding(legacy_binding) = legacy_scope { if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope {
let res = legacy_binding.binding.res(); let res = macro_rules_binding.binding.res();
if filter_fn(res) { if filter_fn(res) {
suggestions suggestions
.push(TypoSuggestion::from_res(legacy_binding.ident.name, res)) .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res))
} }
} }
} }

View File

@ -58,7 +58,7 @@ use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_ne
use diagnostics::{ImportSuggestion, Suggestion}; use diagnostics::{ImportSuggestion, Suggestion};
use imports::{Import, ImportKind, ImportResolver, NameResolution}; use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use late::{HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{LegacyBinding, LegacyScope}; use macros::{MacroRulesBinding, MacroRulesScope};
type Res = def::Res<NodeId>; type Res = def::Res<NodeId>;
@ -94,7 +94,7 @@ impl Determinacy {
enum Scope<'a> { enum Scope<'a> {
DeriveHelpers(ExpnId), DeriveHelpers(ExpnId),
DeriveHelpersCompat, DeriveHelpersCompat,
MacroRules(LegacyScope<'a>), MacroRules(MacroRulesScope<'a>),
CrateRoot, CrateRoot,
Module(Module<'a>), Module(Module<'a>),
RegisteredAttrs, RegisteredAttrs,
@ -127,7 +127,7 @@ enum ScopeSet {
pub struct ParentScope<'a> { pub struct ParentScope<'a> {
module: Module<'a>, module: Module<'a>,
expansion: ExpnId, expansion: ExpnId,
legacy: LegacyScope<'a>, macro_rules: MacroRulesScope<'a>,
derives: &'a [ast::Path], derives: &'a [ast::Path],
} }
@ -135,7 +135,12 @@ impl<'a> ParentScope<'a> {
/// Creates a parent scope with the passed argument used as the module scope component, /// Creates a parent scope with the passed argument used as the module scope component,
/// and other scope components set to default empty values. /// and other scope components set to default empty values.
pub fn module(module: Module<'a>) -> ParentScope<'a> { pub fn module(module: Module<'a>) -> ParentScope<'a> {
ParentScope { module, expansion: ExpnId::root(), legacy: LegacyScope::Empty, derives: &[] } ParentScope {
module,
expansion: ExpnId::root(),
macro_rules: MacroRulesScope::Empty,
derives: &[],
}
} }
} }
@ -930,9 +935,9 @@ pub struct Resolver<'a> {
/// Parent scopes in which the macros were invoked. /// Parent scopes in which the macros were invoked.
/// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>, invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
/// Legacy scopes *produced* by expanding the macro invocations, /// `macro_rules` scopes *produced* by expanding the macro invocations,
/// include all the `macro_rules` items and other invocations generated by them. /// include all the `macro_rules` items and other invocations generated by them.
output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>, output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScope<'a>>,
/// Helper attributes that are in scope for the given expansion. /// Helper attributes that are in scope for the given expansion.
helper_attrs: FxHashMap<ExpnId, Vec<Ident>>, helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
@ -965,7 +970,7 @@ pub struct ResolverArenas<'a> {
name_bindings: arena::TypedArena<NameBinding<'a>>, name_bindings: arena::TypedArena<NameBinding<'a>>,
imports: arena::TypedArena<Import<'a>>, imports: arena::TypedArena<Import<'a>>,
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>, name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>, macro_rules_bindings: arena::TypedArena<MacroRulesBinding<'a>>,
ast_paths: arena::TypedArena<ast::Path>, ast_paths: arena::TypedArena<ast::Path>,
} }
@ -989,8 +994,11 @@ impl<'a> ResolverArenas<'a> {
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default()) self.name_resolutions.alloc(Default::default())
} }
fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { fn alloc_macro_rules_binding(
self.legacy_bindings.alloc(binding) &'a self,
binding: MacroRulesBinding<'a>,
) -> &'a MacroRulesBinding<'a> {
self.macro_rules_bindings.alloc(binding)
} }
fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] {
self.ast_paths.alloc_from_iter(paths.iter().cloned()) self.ast_paths.alloc_from_iter(paths.iter().cloned())
@ -1210,7 +1218,7 @@ impl<'a> Resolver<'a> {
dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
invocation_parent_scopes, invocation_parent_scopes,
output_legacy_scopes: Default::default(), output_macro_rules_scopes: Default::default(),
helper_attrs: Default::default(), helper_attrs: Default::default(),
macro_defs, macro_defs,
local_macro_def_scopes: FxHashMap::default(), local_macro_def_scopes: FxHashMap::default(),
@ -1530,16 +1538,18 @@ impl<'a> Resolver<'a> {
} }
} }
Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat, Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy), Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
Scope::MacroRules(legacy_scope) => match legacy_scope { Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
LegacyScope::Binding(binding) => Scope::MacroRules(binding.parent_legacy_scope), MacroRulesScope::Binding(binding) => {
LegacyScope::Invocation(invoc_id) => Scope::MacroRules( Scope::MacroRules(binding.parent_macro_rules_scope)
self.output_legacy_scopes }
MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules(
self.output_macro_rules_scopes
.get(&invoc_id) .get(&invoc_id)
.cloned() .cloned()
.unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy), .unwrap_or(self.invocation_parent_scopes[&invoc_id].macro_rules),
), ),
LegacyScope::Empty => Scope::Module(module), MacroRulesScope::Empty => Scope::Module(module),
}, },
Scope::CrateRoot => match ns { Scope::CrateRoot => match ns {
TypeNS => { TypeNS => {

View File

@ -33,26 +33,26 @@ use std::{mem, ptr};
type Res = def::Res<NodeId>; type Res = def::Res<NodeId>;
/// Binding produced by a `macro_rules` item. /// Binding produced by a `macro_rules` item.
/// Not modularized, can shadow previous legacy bindings, etc. /// Not modularized, can shadow previous `macro_rules` bindings, etc.
#[derive(Debug)] #[derive(Debug)]
pub struct LegacyBinding<'a> { pub struct MacroRulesBinding<'a> {
crate binding: &'a NameBinding<'a>, crate binding: &'a NameBinding<'a>,
/// Legacy scope into which the `macro_rules` item was planted. /// `macro_rules` scope into which the `macro_rules` item was planted.
crate parent_legacy_scope: LegacyScope<'a>, crate parent_macro_rules_scope: MacroRulesScope<'a>,
crate ident: Ident, crate ident: Ident,
} }
/// The scope introduced by a `macro_rules!` macro. /// The scope introduced by a `macro_rules!` macro.
/// This starts at the macro's definition and ends at the end of the macro's parent /// This starts at the macro's definition and ends at the end of the macro's parent
/// module (named or unnamed), or even further if it escapes with `#[macro_use]`. /// module (named or unnamed), or even further if it escapes with `#[macro_use]`.
/// Some macro invocations need to introduce legacy scopes too because they /// Some macro invocations need to introduce `macro_rules` scopes too because they
/// can potentially expand into macro definitions. /// can potentially expand into macro definitions.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum LegacyScope<'a> { pub enum MacroRulesScope<'a> {
/// Empty "root" scope at the crate start containing no names. /// Empty "root" scope at the crate start containing no names.
Empty, Empty,
/// The scope introduced by a `macro_rules!` macro definition. /// The scope introduced by a `macro_rules!` macro definition.
Binding(&'a LegacyBinding<'a>), Binding(&'a MacroRulesBinding<'a>),
/// The scope introduced by a macro invocation that can potentially /// The scope introduced by a macro invocation that can potentially
/// create a `macro_rules!` macro definition. /// create a `macro_rules!` macro definition.
Invocation(ExpnId), Invocation(ExpnId),
@ -159,8 +159,8 @@ impl<'a> base::Resolver for Resolver<'a> {
// Integrate the new AST fragment into all the definition and module structures. // Integrate the new AST fragment into all the definition and module structures.
// We are inside the `expansion` now, but other parent scope components are still the same. // We are inside the `expansion` now, but other parent scope components are still the same.
let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] };
let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope);
self.output_legacy_scopes.insert(expansion, output_legacy_scope); self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
} }
@ -608,12 +608,14 @@ impl<'a> Resolver<'a> {
} }
result result
} }
Scope::MacroRules(legacy_scope) => match legacy_scope { Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => { MacroRulesScope::Binding(macro_rules_binding)
Ok((legacy_binding.binding, Flags::MACRO_RULES)) if ident == macro_rules_binding.ident =>
{
Ok((macro_rules_binding.binding, Flags::MACRO_RULES))
} }
LegacyScope::Invocation(invoc_id) MacroRulesScope::Invocation(invoc_id)
if !this.output_legacy_scopes.contains_key(&invoc_id) => if !this.output_macro_rules_scopes.contains_key(&invoc_id) =>
{ {
Err(Determinacy::Undetermined) Err(Determinacy::Undetermined)
} }