Skip to content

Commit b0178f4

Browse files
Rollup merge of #79034 - petrochenkov:mrscopes3, r=eddyb
rustc_resolve: Make `macro_rules` scope chain compression lazy As suggested in #78826 (comment).
2 parents 9c6d3c0 + ac4c1f5 commit b0178f4

File tree

3 files changed

+21
-36
lines changed

3 files changed

+21
-36
lines changed

Diff for: compiler/rustc_resolve/src/build_reduced_graph.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1163,9 +1163,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
11631163
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
11641164
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
11651165

1166-
let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id));
1167-
self.r.invocation_macro_rules_scopes.entry(invoc_id).or_default().insert(scope);
1168-
scope
1166+
self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
11691167
}
11701168

11711169
fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {

Diff for: compiler/rustc_resolve/src/lib.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -976,9 +976,6 @@ pub struct Resolver<'a> {
976976
/// `macro_rules` scopes *produced* by expanding the macro invocations,
977977
/// include all the `macro_rules` items and other invocations generated by them.
978978
output_macro_rules_scopes: FxHashMap<ExpnId, MacroRulesScopeRef<'a>>,
979-
/// References to all `MacroRulesScope::Invocation(invoc_id)`s, used to update such scopes
980-
/// when their corresponding `invoc_id`s get expanded.
981-
invocation_macro_rules_scopes: FxHashMap<ExpnId, FxHashSet<MacroRulesScopeRef<'a>>>,
982979
/// Helper attributes that are in scope for the given expansion.
983980
helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
984981

@@ -1310,7 +1307,6 @@ impl<'a> Resolver<'a> {
13101307
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
13111308
invocation_parent_scopes: Default::default(),
13121309
output_macro_rules_scopes: Default::default(),
1313-
invocation_macro_rules_scopes: Default::default(),
13141310
helper_attrs: Default::default(),
13151311
local_macro_def_scopes: FxHashMap::default(),
13161312
name_already_seen: FxHashMap::default(),
@@ -1680,7 +1676,20 @@ impl<'a> Resolver<'a> {
16801676
!(expn_id == parent_scope.expansion && macro_kind == Some(MacroKind::Derive))
16811677
}
16821678
Scope::DeriveHelpersCompat => true,
1683-
Scope::MacroRules(..) => true,
1679+
Scope::MacroRules(macro_rules_scope) => {
1680+
// Use "path compression" on `macro_rules` scope chains. This is an optimization
1681+
// used to avoid long scope chains, see the comments on `MacroRulesScopeRef`.
1682+
// As another consequence of this optimization visitors never observe invocation
1683+
// scopes for macros that were already expanded.
1684+
while let MacroRulesScope::Invocation(invoc_id) = macro_rules_scope.get() {
1685+
if let Some(next_scope) = self.output_macro_rules_scopes.get(&invoc_id) {
1686+
macro_rules_scope.set(next_scope.get());
1687+
} else {
1688+
break;
1689+
}
1690+
}
1691+
true
1692+
}
16841693
Scope::CrateRoot => true,
16851694
Scope::Module(..) => true,
16861695
Scope::RegisteredAttrs => use_prelude,
@@ -1716,11 +1725,9 @@ impl<'a> Resolver<'a> {
17161725
MacroRulesScope::Binding(binding) => {
17171726
Scope::MacroRules(binding.parent_macro_rules_scope)
17181727
}
1719-
MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules(
1720-
self.output_macro_rules_scopes.get(&invoc_id).cloned().unwrap_or_else(
1721-
|| self.invocation_parent_scopes[&invoc_id].macro_rules,
1722-
),
1723-
),
1728+
MacroRulesScope::Invocation(invoc_id) => {
1729+
Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
1730+
}
17241731
MacroRulesScope::Empty => Scope::Module(module),
17251732
},
17261733
Scope::CrateRoot => match ns {

Diff for: compiler/rustc_resolve/src/macros.rs

+3-23
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ pub enum MacroRulesScope<'a> {
6262
}
6363

6464
/// `macro_rules!` scopes are always kept by reference and inside a cell.
65-
/// The reason is that we update all scopes with value `MacroRulesScope::Invocation(invoc_id)`
66-
/// in-place immediately after `invoc_id` gets expanded.
65+
/// The reason is that we update scopes with value `MacroRulesScope::Invocation(invoc_id)`
66+
/// in-place after `invoc_id` gets expanded.
6767
/// This helps to avoid uncontrollable growth of `macro_rules!` scope chains,
6868
/// which usually grow lineraly with the number of macro invocations
6969
/// in a module (including derives) and hurt performance.
@@ -173,22 +173,6 @@ impl<'a> ResolverExpand for Resolver<'a> {
173173
let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope);
174174
self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope);
175175

176-
// Update all `macro_rules` scopes referring to this invocation. This is an optimization
177-
// used to avoid long scope chains, see the comments on `MacroRulesScopeRef`.
178-
if let Some(invocation_scopes) = self.invocation_macro_rules_scopes.remove(&expansion) {
179-
for invocation_scope in &invocation_scopes {
180-
invocation_scope.set(output_macro_rules_scope.get());
181-
}
182-
// All `macro_rules` scopes that previously referred to `expansion`
183-
// are now rerouted to its output scope, if it's also an invocation.
184-
if let MacroRulesScope::Invocation(invoc_id) = output_macro_rules_scope.get() {
185-
self.invocation_macro_rules_scopes
186-
.entry(invoc_id)
187-
.or_default()
188-
.extend(invocation_scopes);
189-
}
190-
}
191-
192176
parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
193177
}
194178

@@ -687,11 +671,7 @@ impl<'a> Resolver<'a> {
687671
{
688672
Ok((macro_rules_binding.binding, Flags::MACRO_RULES))
689673
}
690-
MacroRulesScope::Invocation(invoc_id)
691-
if !this.output_macro_rules_scopes.contains_key(&invoc_id) =>
692-
{
693-
Err(Determinacy::Undetermined)
694-
}
674+
MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined),
695675
_ => Err(Determinacy::Determined),
696676
},
697677
Scope::CrateRoot => {

0 commit comments

Comments
 (0)