Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ impl Resolver<'_, '_> {
let unused_imports = visitor.unused_imports;
let mut check_redundant_imports = FxIndexSet::default();
for module in &self.local_modules {
for (_key, resolution) in self.resolutions(module.to_module()).borrow().iter() {
for (_key, resolution) in self.resolutions(module.to_module()).iter() {
if let Some(decl) = resolution.borrow().best_decl()
&& let DeclKind::Import { import, .. } = decl.kind
&& let ImportKind::Single { id, .. } = import.kind
Expand Down
32 changes: 15 additions & 17 deletions compiler/rustc_resolve/src/diagnostics/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1870,24 +1870,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// If so, we have to disambiguate the potential import suggestions by making
// the paths *global* (i.e., by prefixing them with `::`).
let needs_disambiguation =
self.resolutions(parent_scope.module).borrow().iter().any(
|(key, name_resolution)| {
if key.ns == TypeNS
&& key.ident == *ident
&& let Some(decl) = name_resolution.borrow().best_decl()
{
match decl.res() {
// No disambiguation needed if the identically named item we
// found in scope actually refers to the crate in question.
Res::Def(_, def_id) => def_id != crate_def_id,
Res::PrimTy(_) => true,
_ => false,
}
} else {
false
self.resolutions(parent_scope.module).iter().any(|(key, name_resolution)| {
if key.ns == TypeNS
&& key.ident == *ident
&& let Some(decl) = name_resolution.borrow().best_decl()
{
match decl.res() {
// No disambiguation needed if the identically named item we
// found in scope actually refers to the crate in question.
Res::Def(_, def_id) => def_id != crate_def_id,
Res::PrimTy(_) => true,
_ => false,
}
},
);
} else {
false
}
});
let mut crate_path = ThinVec::new();
if needs_disambiguation {
crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/effective_visibilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
/// 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());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
for (_, name_resolution) in self.r.resolutions(module).iter() {
let Some(decl) = name_resolution.borrow().best_decl() else {
continue;
};
Expand Down Expand Up @@ -309,7 +309,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
) {
if self.macro_reachable.insert((module_def_id, defining_mod)) {
let module = self.r.expect_module(module_def_id.to_def_id());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
for (_, name_resolution) in self.r.resolutions(module).iter() {
let Some(decl) = name_resolution.borrow().best_decl() else {
continue;
};
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {
for module in &self.local_modules {
for (key, resolution) in self.resolutions(module.to_module()).borrow().iter() {
for (key, resolution) in self.resolutions(module.to_module()).iter() {
let resolution = resolution.borrow();
let Some(binding) = resolution.best_decl() else { continue };

Expand Down Expand Up @@ -1481,7 +1481,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let names = match module {
ModuleOrUniformRoot::Module(module) => {
self.resolutions(module)
.borrow()
.iter()
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
if i.name == ident.name {
Expand Down Expand Up @@ -1799,7 +1798,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let import_bindings = match imported_module {
ModuleOrUniformRoot::Module(module) if module != import.parent_scope.module => self
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
let res = resolution.borrow();
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
assoc_name: Symbol,
) -> Option<DefId> {
let module = self.r.get_module(trait_def_id)?;
self.r.resolutions(module).borrow().iter().find_map(|(key, resolution)| {
self.r.resolutions(module).iter().find_map(|(key, resolution)| {
if key.ident.name != assoc_name {
return None;
}
Expand Down Expand Up @@ -648,7 +648,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
&& self
.r
.resolutions(module)
.borrow()
.iter()
.any(|(key, _r)| key.ident.name == following_seg.ident.name)
} else {
Expand Down Expand Up @@ -1164,7 +1163,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {

fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
for resolution in r.resolutions(m).borrow().values() {
for resolution in r.resolutions(m).values() {
let Some(did) =
resolution.borrow().best_decl().and_then(|binding| binding.res().opt_def_id())
else {
Expand Down Expand Up @@ -1904,7 +1903,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let targets: Vec<_> = self
.r
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
let resolution = resolution.borrow();
Expand Down Expand Up @@ -2767,7 +2765,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let targets = self
.r
.resolutions(*module)
.borrow()
.iter()
.filter_map(|(key, res)| res.borrow().best_decl().map(|binding| (key, binding.res())))
.filter(|(_, res)| match (kind, res) {
Expand Down Expand Up @@ -2970,7 +2967,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let module = self.r.expect_module(def_id);
self.r
.resolutions(module)
.borrow()
.iter()
.any(|(key, _)| key.ident.name == following_seg.ident.name)
}
Expand Down
64 changes: 46 additions & 18 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#![recursion_limit = "256"]
// tidy-alphabetical-end

use std::cell::Ref;
use std::cell::{Ref, RefMut};
use std::collections::BTreeSet;
use std::ops::ControlFlow;
use std::sync::{Arc, OnceLock};
Expand Down Expand Up @@ -81,7 +81,7 @@ use crate::diagnostics::impls::{
ImportSuggestion, LabelSuggestion, OnUnknownData, StructCtor, Suggestion,
};
use crate::imports::{ImportResolution, NameResolutionRef};
use crate::ref_mut::{CmCell, CmRefCell};
use crate::ref_mut::{CmCell, CmRef, CmRefCell};

mod build_reduced_graph;
mod check_unused;
Expand Down Expand Up @@ -637,7 +637,7 @@ type ResolutionTable<'ra> = FxIndexMap<BindingKey, NameResolutionRef<'ra>>;

enum Resolutions<'ra> {
Local(CmRefCell<ResolutionTable<'ra>>),
Extern(OnceLock<CmRefCell<ResolutionTable<'ra>>>),
Extern(OnceLock<ResolutionTable<'ra>>),
}

impl<'ra> Resolutions<'ra> {
Expand Down Expand Up @@ -792,7 +792,7 @@ impl<'ra> Module<'ra> {
resolver: &R,
mut f: impl FnMut(&R, IdentKey, Span, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
for (key, name_resolution) in resolver.as_ref().resolutions(self).iter() {
let name_resolution = name_resolution.borrow();
if let Some(decl) = name_resolution.best_decl() {
f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
Expand All @@ -805,7 +805,7 @@ impl<'ra> Module<'ra> {
resolver: &mut R,
mut f: impl FnMut(&mut R, IdentKey, Span, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
for (key, name_resolution) in resolver.as_mut().resolutions(self).iter() {
let name_resolution = name_resolution.borrow();
if let Some(decl) = name_resolution.best_decl() {
f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
Expand Down Expand Up @@ -2152,7 +2152,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
match (trait_module, assoc_item) {
(Some(trait_module), Some((name, ns))) => self
.resolutions(trait_module)
.borrow()
.iter()
.any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
_ => true,
Expand All @@ -2177,14 +2176,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.tcx.hir_arena.alloc_slice(&import_ids)
}

fn resolutions(&self, module: Module<'ra>) -> &'ra CmRefCell<ResolutionTable<'ra>> {
fn resolutions(&self, module: Module<'ra>) -> CmRef<'ra, ResolutionTable<'ra>> {
match &module.0.0.lazy_resolutions {
Resolutions::Local(local_res) => local_res,
Resolutions::Local(local_res) => CmRef::Tracked(local_res.borrow()),
Resolutions::Extern(extern_res) => {
// as long as 1 thread is building this external table, all other threads will wait
extern_res.get_or_init(|| {
CmRefCell::new(self.build_reduced_graph_external(module.expect_extern()))
})
// It is fine to return a `CmRef::Untracked`, we never give out a `&mut`
// to an external table.
CmRef::Untracked(
// As long as 1 thread is building this external table, all other threads will wait.
extern_res
.get_or_init(|| self.build_reduced_graph_external(module.expect_extern())),
)
}
}
}

fn resolutions_mut(&self, module: Module<'ra>) -> RefMut<'ra, ResolutionTable<'ra>> {
match &module.0.0.lazy_resolutions {
Resolutions::Local(local_res) => local_res.borrow_mut(self),
Resolutions::Extern(_) => {
// We do not allow in place mutations of the external resolution table. In fact,
// we never attempt it.
unreachable!("Attempted to mutably borrow an extenral resolution table")
}
}
}
Expand All @@ -2194,7 +2207,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module: Module<'ra>,
key: BindingKey,
) -> Option<Ref<'ra, NameResolution<'ra>>> {
self.resolutions(module).borrow().get(&key).map(|resolution| resolution.0.borrow())
self.resolutions(module).get(&key).map(|resolution| resolution.0.borrow())
}

#[track_caller]
Expand All @@ -2204,7 +2217,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
key: BindingKey,
orig_ident_span: Span,
) -> NameResolutionRef<'ra> {
*self.resolutions(module).borrow_mut(self).entry(key).or_insert_with(|| {
*self.resolutions_mut(module).entry(key).or_insert_with(|| {
self.arenas.alloc_name_resolution(NameResolution::new(orig_ident_span))
})
}
Expand Down Expand Up @@ -2915,6 +2928,24 @@ mod ref_mut {
}
}

pub(crate) enum CmRef<'b, T> {
/// A tracked borrow of a [`CmRefCell`]
Tracked(Ref<'b, T>),
/// An untracked or normal reference (not dynamically borrow-checked by `RefCell`)
Untracked(&'b T),
}

impl<'b, T> Deref for CmRef<'b, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
match self {
CmRef::Tracked(r) => r,
CmRef::Untracked(r) => r,
}
}
}

/// A wrapper around a [`RefCell`] that only allows writes (mutable borrows) based on a condition in the resolver.
#[derive(Default)]
pub(crate) struct CmRefCell<T>(RefCell<T>);
Expand All @@ -2926,10 +2957,7 @@ mod ref_mut {

#[track_caller]
pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> RefMut<'_, T> {
if r.assert_speculative {
panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution");
}
self.0.borrow_mut()
self.try_borrow_mut(r).unwrap()
}

#[track_caller]
Expand Down
Loading