Skip to content

Commit e820112

Browse files
committed
resolve: Do not create NameResolutions on access unless necessary
1 parent 2c65790 commit e820112

File tree

6 files changed

+23
-15
lines changed

6 files changed

+23
-15
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
452452
self.r.per_ns(|this, ns| {
453453
if !type_ns_only || ns == TypeNS {
454454
let key = BindingKey::new(target, ns);
455-
this.resolution(current_module, key)
455+
this.resolution_or_default(current_module, key)
456456
.borrow_mut()
457457
.single_imports
458458
.insert(import);

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2660,8 +2660,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
26602660
}
26612661

26622662
let binding_key = BindingKey::new(ident, MacroNS);
2663-
let binding =
2664-
self.resolutions(crate_module).borrow().get(&binding_key)?.borrow().binding()?;
2663+
let binding = self.resolution(crate_module, binding_key)?.binding()?;
26652664
let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
26662665
return None;
26672666
};

compiler/rustc_resolve/src/ident.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -848,8 +848,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
848848
};
849849

850850
let key = BindingKey::new(ident, ns);
851-
let resolution =
852-
self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
851+
// `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
852+
// doesn't need to be mutable. It will fail when there is a cycle of imports, and without
853+
// the exclusive access infinite recursion will crash the compiler with stack overflow.
854+
let resolution = &*self
855+
.resolution_or_default(module, key)
856+
.try_borrow_mut()
857+
.map_err(|_| (Determined, Weak::No))?;
853858

854859
// If the primary binding is unusable, search further and return the shadowed glob
855860
// binding if it exists. What we really want here is having two separate scopes in

compiler/rustc_resolve/src/imports.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
469469
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
470470
// during which the resolution might end up getting re-defined via a glob cycle.
471471
let (binding, t, warn_ambiguity) = {
472-
let resolution = &mut *self.resolution(module, key).borrow_mut();
472+
let resolution = &mut *self.resolution_or_default(module, key).borrow_mut();
473473
let old_binding = resolution.binding();
474474

475475
let t = f(self, resolution);
@@ -1514,8 +1514,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15141514
let imported_binding = self.import(binding, import);
15151515
let warn_ambiguity = self
15161516
.resolution(import.parent_scope.module, key)
1517-
.borrow()
1518-
.binding()
1517+
.and_then(|r| r.binding())
15191518
.is_some_and(|binding| binding.warn_ambiguity_recursive());
15201519
let _ = self.try_define(
15211520
import.parent_scope.module,

compiler/rustc_resolve/src/late.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3449,8 +3449,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34493449
};
34503450
ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
34513451
let key = BindingKey::new(ident, ns);
3452-
let mut binding =
3453-
self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding());
3452+
let mut binding = self.r.resolution(module, key).and_then(|r| r.best_binding());
34543453
debug!(?binding);
34553454
if binding.is_none() {
34563455
// We could not find the trait item in the correct namespace.
@@ -3461,8 +3460,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
34613460
_ => ns,
34623461
};
34633462
let key = BindingKey::new(ident, ns);
3464-
binding =
3465-
self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding());
3463+
binding = self.r.resolution(module, key).and_then(|r| r.best_binding());
34663464
debug!(?binding);
34673465
}
34683466

compiler/rustc_resolve/src/lib.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#![recursion_limit = "256"]
2222
// tidy-alphabetical-end
2323

24-
use std::cell::{Cell, RefCell};
24+
use std::cell::{Cell, Ref, RefCell};
2525
use std::collections::BTreeSet;
2626
use std::fmt;
2727
use std::sync::Arc;
@@ -1905,9 +1905,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19051905
&mut self,
19061906
module: Module<'ra>,
19071907
key: BindingKey,
1908+
) -> Option<Ref<'ra, NameResolution<'ra>>> {
1909+
self.resolutions(module).borrow().get(&key).map(|resolution| resolution.borrow())
1910+
}
1911+
1912+
fn resolution_or_default(
1913+
&mut self,
1914+
module: Module<'ra>,
1915+
key: BindingKey,
19081916
) -> &'ra RefCell<NameResolution<'ra>> {
1909-
*self
1910-
.resolutions(module)
1917+
self.resolutions(module)
19111918
.borrow_mut()
19121919
.entry(key)
19131920
.or_insert_with(|| self.arenas.alloc_name_resolution())

0 commit comments

Comments
 (0)