Rollup merge of #144468 - petrochenkov:resolution, r=lqd,SparrowLii

resolve: Do not create `NameResolutions` on access unless necessary

`fn resolution` now just performs the access, and `fn resolution_or_default` will insert a default entry if the entry is missing.
This commit is contained in:
Matthias Krüger
2025-07-26 15:28:04 +02:00
committed by GitHub
9 changed files with 66 additions and 61 deletions
@@ -452,8 +452,10 @@ fn add_import(
self.r.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let key = BindingKey::new(target, ns);
let mut resolution = this.resolution(current_module, key).borrow_mut();
resolution.single_imports.insert(import);
this.resolution_or_default(current_module, key)
.borrow_mut()
.single_imports
.insert(import);
}
});
}
+1 -3
View File
@@ -509,9 +509,7 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
let mut check_redundant_imports = FxIndexSet::default();
for module in self.arenas.local_modules().iter() {
for (_key, resolution) in self.resolutions(*module).borrow().iter() {
let resolution = resolution.borrow();
if let Some(binding) = resolution.best_binding()
if let Some(binding) = resolution.borrow().best_binding()
&& let NameBindingKind::Import { import, .. } = binding.kind
&& let ImportKind::Single { id, .. } = import.kind
{
+1 -3
View File
@@ -2659,10 +2659,8 @@ pub(crate) fn check_for_module_export_macro(
return None;
}
let resolutions = self.resolutions(crate_module).borrow();
let binding_key = BindingKey::new(ident, MacroNS);
let resolution = resolutions.get(&binding_key)?;
let binding = resolution.borrow().binding()?;
let binding = self.resolution(crate_module, binding_key)?.binding()?;
let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
return None;
};
@@ -114,9 +114,7 @@ pub(crate) fn compute_effective_visibilities<'c>(
/// including their whole reexport chains.
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
let module = self.r.expect_module(module_id.to_def_id());
let resolutions = self.r.resolutions(module);
for (_, name_resolution) in resolutions.borrow().iter() {
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
let Some(mut binding) = name_resolution.borrow().binding() else {
continue;
};
+7 -2
View File
@@ -848,8 +848,13 @@ fn resolve_ident_in_module_unadjusted(
};
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
+32 -36
View File
@@ -469,7 +469,7 @@ fn update_resolution<T, F>(
// 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);
@@ -651,7 +651,6 @@ pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<NameBind
for module in self.arenas.local_modules().iter() {
for (key, resolution) in self.resolutions(*module).borrow().iter() {
let resolution = resolution.borrow();
let Some(binding) = resolution.best_binding() else { continue };
if let NameBindingKind::Import { import, .. } = binding.kind
@@ -1202,41 +1201,39 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
});
return if all_ns_failed {
let resolutions = match module {
ModuleOrUniformRoot::Module(module) => Some(self.resolutions(module).borrow()),
_ => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
let names = resolutions
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
if i.name == ident.name {
return None;
} // Never suggest the same name
match *resolution.borrow() {
ref resolution
if let Some(name_binding) = resolution.best_binding() =>
{
match name_binding.kind {
NameBindingKind::Import { binding, .. } => {
match binding.kind {
// Never suggest the name that has binding error
// i.e., the name that cannot be previously resolved
NameBindingKind::Res(Res::Err) => None,
_ => Some(i.name),
let names = match module {
ModuleOrUniformRoot::Module(module) => {
self.resolutions(module)
.borrow()
.iter()
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
if i.name == ident.name {
return None;
} // Never suggest the same name
let resolution = resolution.borrow();
if let Some(name_binding) = resolution.best_binding() {
match name_binding.kind {
NameBindingKind::Import { binding, .. } => {
match binding.kind {
// Never suggest the name that has binding error
// i.e., the name that cannot be previously resolved
NameBindingKind::Res(Res::Err) => None,
_ => Some(i.name),
}
}
_ => Some(i.name),
}
_ => Some(i.name),
} else if resolution.single_imports.is_empty() {
None
} else {
Some(i.name)
}
}
NameResolution { ref single_imports, .. }
if single_imports.is_empty() =>
{
None
}
_ => Some(i.name),
}
})
.collect::<Vec<Symbol>>();
})
.collect()
}
_ => Vec::new(),
};
let lev_suggestion =
find_best_match_for_name(&names, ident.name, None).map(|suggestion| {
@@ -1517,8 +1514,7 @@ fn resolve_glob_import(&mut self, import: Import<'ra>) {
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,
+2 -4
View File
@@ -3449,8 +3449,7 @@ fn check_trait_item<F>(
};
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 @@ fn check_trait_item<F>(
_ => 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);
}
@@ -1461,15 +1461,17 @@ fn get_single_associated_item(
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, None, None)
{
let resolutions = self.r.resolutions(module).borrow();
let targets: Vec<_> = resolutions
let targets: Vec<_> = self
.r
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
resolution
.borrow()
.best_binding()
.map(|binding| binding.res())
.and_then(|res| if filter_fn(res) { Some((key, res)) } else { None })
.and_then(|res| if filter_fn(res) { Some((*key, res)) } else { None })
})
.collect();
if let [target] = targets.as_slice() {
@@ -2300,8 +2302,9 @@ pub(crate) fn find_similarly_named_assoc_item(
return None;
}
let resolutions = self.r.resolutions(*module);
let targets = resolutions
let targets = self
.r
.resolutions(*module)
.borrow()
.iter()
.filter_map(|(key, res)| {
+10 -3
View File
@@ -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 @@ fn resolution(
&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())