diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index ad00003af9482..8ce95f80633b0 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -567,7 +567,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { // Don't add underscore imports to `single_imports` // because they cannot define any usable names. if target.name != kw::Underscore { - self.r.per_ns(|this, ns| { + self.r.per_ns_mut(|this, ns| { let key = BindingKey::new(IdentKey::new(target), ns); this.resolution_or_default(current_module.to_module(), key, target.span) .borrow_mut(this) diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index dcbda2f96323e..52e46bb21a9f3 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -559,7 +559,7 @@ impl Resolver<'_, '_> { let mut check_redundant_imports = FxIndexSet::default(); for module in &self.local_modules { for (_key, resolution) in self.resolutions(module.to_module()).iter() { - if let Some(decl) = resolution.borrow(self).best_decl() + if let Some(decl) = resolution.borrow_checked(self).best_decl() && let DeclKind::Import { import, .. } = decl.kind && let ImportKind::Single { id, .. } = import.kind { diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 97c2c2f327ccf..00b1c9ca0c5f3 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1873,7 +1873,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.resolutions(parent_scope.module).iter().any(|(key, name_resolution)| { if key.ns == TypeNS && key.ident == *ident - && let Some(decl) = name_resolution.borrow(self).best_decl() + && let Some(decl) = name_resolution.borrow_checked(self).best_decl() { match decl.res() { // No disambiguation needed if the identically named item we @@ -3634,7 +3634,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut res = false; let m = r.expect_module(parent_module); if m.is_local() { - for importer in m.glob_importers.borrow(r).iter() { + for importer in m.glob_importers.borrow_checked(r).iter() { if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() { if next_parent_module == module diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 2a1b208f94c34..000af0f38534a 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1290,7 +1290,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Check if one of glob imports can still define the name, // if it can then our "no resolution" result is not determined and can be invalidated. - for glob_import in module.globs.borrow(&self).iter() { + for glob_import in module.globs.borrow_checked(&self).iter() { if ignore_import == Some(*glob_import) { continue; } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 499f9ea297362..749e414d2ba9e 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -468,7 +468,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { || max_vis.get().is_none_or(|max_vis| vis.greater_than(max_vis, self.tcx))) { // `set` can't fail because this can only happen during "write_import_resolutions" - max_vis.set(Some(vis), self) + max_vis.set_checked(Some(vis), self) } self.arenas.alloc_decl(DeclData { @@ -585,7 +585,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && glob_decl.ambiguity.get().is_none() { // Do not lose glob ambiguities when re-fetching the glob. - glob_decl.ambiguity.set(Some((old_ambig, true)), self); + glob_decl.ambiguity.set_checked(Some((old_ambig, true)), self); } glob_decl } else if glob_decl.res() != old_glob_decl.res() { @@ -593,7 +593,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { || self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl) || self.is_pdf_0_9_0(old_glob_decl, glob_decl) || self.is_net2_0_2_39(old_glob_decl, glob_decl); - old_glob_decl.ambiguity.set(Some((glob_decl, warning)), self); + old_glob_decl.ambiguity.set_checked(Some((glob_decl, warning)), self); old_glob_decl } else if let old_vis = old_glob_decl.vis() && let vis = glob_decl.vis() @@ -602,17 +602,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We are glob-importing the same item but with a different visibility. // All visibilities here are ordered because all of them are ancestors of `module`. if vis.greater_than(old_vis, self.tcx) { - old_glob_decl.ambiguity_vis_max.set(Some(glob_decl), self); + old_glob_decl.ambiguity_vis_max.set_checked(Some(glob_decl), self); } else if let old_min_vis = old_glob_decl.min_vis() && old_min_vis != vis && old_min_vis.greater_than(vis, self.tcx) { - old_glob_decl.ambiguity_vis_min.set(Some(glob_decl), self); + old_glob_decl.ambiguity_vis_min.set_checked(Some(glob_decl), self); } old_glob_decl } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() { // Overwriting a non-ambiguous glob import with an ambiguous glob import. - old_glob_decl.ambiguity.set(Some((glob_decl, true)), self); + old_glob_decl.ambiguity.set_checked(Some((glob_decl, true)), self); old_glob_decl } else { old_glob_decl @@ -1011,7 +1011,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet>) { for module in &self.local_modules { for (key, resolution) in self.resolutions(module.to_module()).iter() { - let resolution = resolution.borrow(self); + let resolution = resolution.borrow_checked(self); let Some(binding) = resolution.best_decl() else { continue }; // Report "cannot reexport" errors for exotic cases involving macros 2.0 @@ -1808,7 +1808,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .resolutions(module) .iter() .filter_map(|(key, resolution)| { - let res = resolution.borrow(self); + let res = resolution.borrow_checked(self); let decl = res.determined_decl()?; let mut key = *key; let scope = match key.ident.ctxt.update_unchecked(|ctxt| { @@ -1874,7 +1874,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ambig_module_children: &mut LocalDefIdMap>, ) { // Since import resolution is finished, globs will not define any more names. - *module.globs.borrow_mut(self) = Vec::new(); + *module.globs.borrow_mut_checked(self) = Vec::new(); let Some(def_id) = module.opt_def_id() else { return }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b7e57ad8ec37e..2b02fe136f2ad 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -769,7 +769,7 @@ impl<'ra> ModuleData<'ra> { } fn has_unexpanded_invocations<'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> bool { - !self.unexpanded_invocations.borrow(r).is_empty() + !self.unexpanded_invocations.borrow_checked(r).is_empty() } fn res(&self) -> Option { @@ -794,7 +794,7 @@ impl<'ra> Module<'ra> { mut f: impl FnMut(&R, IdentKey, Span, Namespace, Decl<'ra>), ) { for (key, name_resolution) in resolver.as_ref().resolutions(self).iter() { - let name_resolution = name_resolution.borrow(resolver.as_ref()); + let name_resolution = name_resolution.borrow_checked(resolver.as_ref()); if let Some(decl) = name_resolution.best_decl() { f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl); } @@ -816,7 +816,7 @@ impl<'ra> Module<'ra> { /// This modifies `self` in place. The traits will be stored in `self.traits`. fn ensure_traits<'tcx>(self, resolver: &Resolver<'ra, 'tcx>) { - let mut traits = self.traits.borrow_mut(resolver.as_ref()); + let mut traits = self.traits.borrow_mut_checked(resolver); if traits.is_none() { let mut collected_traits = Vec::new(); self.for_each_child(resolver, |r, ident, _, ns, mut decl| { @@ -2184,7 +2184,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolutions(&self, module: Module<'ra>) -> CmRef<'ra, ResolutionTable<'ra>> { match &module.0.0.lazy_resolutions { - Resolutions::Local(local_res) => local_res.borrow(self), + Resolutions::Local(local_res) => local_res.borrow_checked(self), Resolutions::Extern(extern_res) => { // It is fine to return a `CmRef::Untracked`, we never give out a `&mut` // to an external table. @@ -2197,7 +2197,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - fn resolutions_mut(&self, module: Module<'ra>) -> RefMut<'ra, ResolutionTable<'ra>> { + fn resolutions_mut(&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(_) => { @@ -2213,12 +2213,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module: Module<'ra>, key: BindingKey, ) -> Option>> { - self.resolutions(module).get(&key).map(|resolution| resolution.0.borrow(self)) + self.resolutions(module).get(&key).map(|resolution| resolution.0.borrow_checked(self)) } #[track_caller] fn resolution_or_default( - &self, + &mut self, module: Module<'ra>, key: BindingKey, orig_ident_span: Span, @@ -2908,10 +2908,11 @@ mod ref_mut { self.0.get() } - pub(crate) fn update<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>, f: impl FnOnce(T) -> T) - where - T: Copy, - { + pub(crate) fn update<'ra, 'tcx>( + &self, + r: &mut Resolver<'ra, 'tcx>, + f: impl FnOnce(T) -> T, + ) { let old = self.get(); self.set(f(old), r); } @@ -2922,10 +2923,15 @@ mod ref_mut { CmCell(Cell::new(value)) } - pub(crate) fn set<'ra, 'tcx>(&self, val: T, r: &Resolver<'ra, 'tcx>) { - if r.speculative_flag.is_speculative() { - panic!("not allowed to mutate a `CmCell` during speculative resolution") - } + pub(crate) fn set<'ra, 'tcx>(&self, val: T, _: &mut Resolver<'ra, 'tcx>) { + self.0.set(val); + } + + pub(crate) fn set_checked<'ra, 'tcx>(&self, val: T, r: &Resolver<'ra, 'tcx>) { + assert!( + !r.speculative_flag.is_speculative(), + "Cannot mutate `CmCell` during speculative resolution" + ); self.0.set(val); } @@ -2983,23 +2989,43 @@ mod ref_mut { } #[track_caller] - pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> RefMut<'_, T> { + pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &mut Resolver<'ra, 'tcx>) -> RefMut<'_, T> { self.try_borrow_mut(r).unwrap() } #[track_caller] - pub(crate) fn try_borrow_mut<'ra, 'tcx>( + pub(crate) fn borrow_mut_checked<'ra, 'tcx>( + &self, + r: &Resolver<'ra, 'tcx>, + ) -> RefMut<'_, T> { + self.try_borrow_mut_checked(r).unwrap() + } + + #[track_caller] + pub(crate) fn try_borrow_mut_checked<'ra, 'tcx>( &self, r: &Resolver<'ra, 'tcx>, ) -> Result, BorrowMutError> { - if r.speculative_flag.is_speculative() { - panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution"); - } + assert!( + !r.speculative_flag.is_speculative(), + "Cannot mutate `CmRefCell` state/value during speculative resolution" + ); self.0.try_borrow_mut() } #[track_caller] - pub(crate) fn borrow<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> CmRef<'_, T> { + pub(crate) fn try_borrow_mut<'ra, 'tcx>( + &self, + _: &mut Resolver<'ra, 'tcx>, + ) -> Result, BorrowMutError> { + self.0.try_borrow_mut() + } + + pub(crate) fn borrow<'ra, 'tcx>(&self, _: &mut Resolver<'ra, 'tcx>) -> Ref<'_, T> { + self.0.borrow() + } + + pub(crate) fn borrow_checked<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> CmRef<'_, T> { if r.speculative_flag.is_speculative() { // `try_borrow_unguarded` is unsafe because it returns a `&T` instead // of `Ref<'_, T>`. It does provides an extra check to make sure no live diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6921d0ed595fe..ebff3e29e6b19 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -861,7 +861,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PathResult::Module(..) => unreachable!(), }; - self.multi_segment_macro_resolutions.borrow_mut(&self).push(( + self.multi_segment_macro_resolutions.borrow_mut_checked(&self).push(( path, path_span, kind, @@ -888,7 +888,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Err(Determinacy::Undetermined); } - self.single_segment_macro_resolutions.borrow_mut(&self).push(( + self.single_segment_macro_resolutions.borrow_mut_checked(&self).push(( path[0].ident, kind, *parent_scope,