Auto merge of #78826 - petrochenkov:mrscopes2, r=eddyb

resolve: Collapse `macro_rules` scope chains on the fly

Otherwise they grow too long and you have to endlessly walk through them when resolving macros or imports.
Addresses 215750815
This commit is contained in:
bors 2020-11-13 05:40:37 +00:00
commit a38f8fb674
6 changed files with 70 additions and 30 deletions

View file

@ -65,7 +65,7 @@ use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_ne
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{MacroRulesBinding, MacroRulesScope};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
type Res = def::Res<NodeId>;
@ -101,7 +101,7 @@ impl Determinacy {
enum Scope<'a> {
DeriveHelpers(ExpnId),
DeriveHelpersCompat,
MacroRules(MacroRulesScope<'a>),
MacroRules(MacroRulesScopeRef<'a>),
CrateRoot,
Module(Module<'a>),
RegisteredAttrs,
@ -134,18 +134,18 @@ enum ScopeSet {
pub struct ParentScope<'a> {
module: Module<'a>,
expansion: ExpnId,
macro_rules: MacroRulesScope<'a>,
macro_rules: MacroRulesScopeRef<'a>,
derives: &'a [ast::Path],
}
impl<'a> ParentScope<'a> {
/// Creates a parent scope with the passed argument used as the module scope component,
/// and other scope components set to default empty values.
pub fn module(module: Module<'a>) -> ParentScope<'a> {
pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> {
ParentScope {
module,
expansion: ExpnId::root(),
macro_rules: MacroRulesScope::Empty,
macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
derives: &[],
}
}
@ -975,7 +975,10 @@ pub struct Resolver<'a> {
invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>,
/// `macro_rules` scopes *produced* by expanding the macro invocations,
/// include all the `macro_rules` items and other invocations generated by them.
output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScope<'a>>,
output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScopeRef<'a>>,
/// References to all `MacroRulesScope::Invocation(invoc_id)`s, used to update such scopes
/// when their corresponding `invoc_id`s get expanded.
invocation_macro_rules_scopes: FxHashMap<ExpnId, FxHashSet<MacroRulesScopeRef<'a>>>,
/// Helper attributes that are in scope for the given expansion.
helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
@ -1044,6 +1047,9 @@ impl<'a> ResolverArenas<'a> {
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default())
}
fn alloc_macro_rules_scope(&'a self, scope: MacroRulesScope<'a>) -> MacroRulesScopeRef<'a> {
PtrKey(self.dropless.alloc(Cell::new(scope)))
}
fn alloc_macro_rules_binding(
&'a self,
binding: MacroRulesBinding<'a>,
@ -1231,14 +1237,11 @@ impl<'a> Resolver<'a> {
let (registered_attrs, registered_tools) =
macros::registered_attrs_and_tools(session, &krate.attrs);
let mut invocation_parent_scopes = FxHashMap::default();
invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root));
let features = session.features_untracked();
let non_macro_attr =
|mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
Resolver {
let mut resolver = Resolver {
session,
definitions,
@ -1305,8 +1308,9 @@ 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)],
invocation_parent_scopes,
invocation_parent_scopes: Default::default(),
output_macro_rules_scopes: Default::default(),
invocation_macro_rules_scopes: Default::default(),
helper_attrs: Default::default(),
local_macro_def_scopes: FxHashMap::default(),
name_already_seen: FxHashMap::default(),
@ -1333,7 +1337,12 @@ impl<'a> Resolver<'a> {
invocation_parents,
next_disambiguator: Default::default(),
trait_impl_items: Default::default(),
}
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
resolver.invocation_parent_scopes.insert(ExpnId::root(), root_parent_scope);
resolver
}
pub fn next_node_id(&mut self) -> NodeId {
@ -1703,7 +1712,7 @@ impl<'a> Resolver<'a> {
}
Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope {
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
MacroRulesScope::Binding(binding) => {
Scope::MacroRules(binding.parent_macro_rules_scope)
}
@ -3200,7 +3209,7 @@ impl<'a> Resolver<'a> {
}
};
let module = self.get_module(module_id);
let parent_scope = &ParentScope::module(module);
let parent_scope = &ParentScope::module(module, self);
let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?;
Ok((path, res))
}