diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2025-07-26 00:21:01 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2025-07-26 00:25:26 +0300 |
| commit | e82011255b5feb43cf3379d4d3495629e99c09b1 (patch) | |
| tree | c92932f9403b9bd11e400d6256ea79dcd559f0eb | |
| parent | 2c657901605ed5e6e6d3ab52e824f35e25cf4516 (diff) | |
| download | rust-e82011255b5feb43cf3379d4d3495629e99c09b1.tar.gz rust-e82011255b5feb43cf3379d4d3495629e99c09b1.zip | |
resolve: Do not create `NameResolution`s on access unless necessary
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 13 |
6 files changed, 23 insertions, 15 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 13fc068f8a3..ac64385d664 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -452,7 +452,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { let key = BindingKey::new(target, ns); - this.resolution(current_module, key) + this.resolution_or_default(current_module, key) .borrow_mut() .single_imports .insert(import); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 2251539738c..13cf700fbb2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2660,8 +2660,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let binding_key = BindingKey::new(ident, MacroNS); - let binding = - self.resolutions(crate_module).borrow().get(&binding_key)?.borrow().binding()?; + let binding = self.resolution(crate_module, binding_key)?.binding()?; let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else { return None; }; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 71cc68af499..f5bc46bf053 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -848,8 +848,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let key = BindingKey::new(ident, ns); - let resolution = - self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. + // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding + // doesn't need to be mutable. It will fail when there is a cycle of imports, and without + // the exclusive access infinite recursion will crash the compiler with stack overflow. + let resolution = &*self + .resolution_or_default(module, key) + .try_borrow_mut() + .map_err(|_| (Determined, Weak::No))?; // If the primary binding is unusable, search further and return the shadowed glob // binding if it exists. What we really want here is having two separate scopes in diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index ee82afd9676..f2de57b4d50 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -469,7 +469,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t, warn_ambiguity) = { - let resolution = &mut *self.resolution(module, key).borrow_mut(); + let resolution = &mut *self.resolution_or_default(module, key).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); @@ -1514,8 +1514,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let imported_binding = self.import(binding, import); let warn_ambiguity = self .resolution(import.parent_scope.module, key) - .borrow() - .binding() + .and_then(|r| r.binding()) .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_define( import.parent_scope.module, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a3a770502de..ed9622a0d81 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3449,8 +3449,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }; ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); let key = BindingKey::new(ident, ns); - let mut binding = - self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding()); + let mut binding = self.r.resolution(module, key).and_then(|r| r.best_binding()); debug!(?binding); if binding.is_none() { // 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> { _ => ns, }; let key = BindingKey::new(ident, ns); - binding = - self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding()); + binding = self.r.resolution(module, key).and_then(|r| r.best_binding()); debug!(?binding); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 27e14e0e62b..fe7ed07c46e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -21,7 +21,7 @@ #![recursion_limit = "256"] // tidy-alphabetical-end -use std::cell::{Cell, RefCell}; +use std::cell::{Cell, Ref, RefCell}; use std::collections::BTreeSet; use std::fmt; use std::sync::Arc; @@ -1905,9 +1905,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, module: Module<'ra>, key: BindingKey, + ) -> Option<Ref<'ra, NameResolution<'ra>>> { + self.resolutions(module).borrow().get(&key).map(|resolution| resolution.borrow()) + } + + fn resolution_or_default( + &mut self, + module: Module<'ra>, + key: BindingKey, ) -> &'ra RefCell<NameResolution<'ra>> { - *self - .resolutions(module) + self.resolutions(module) .borrow_mut() .entry(key) .or_insert_with(|| self.arenas.alloc_name_resolution()) |
