diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4ce07ffe45ed7..b723516b70edf 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -279,7 +279,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { res, )) }; - match self.cm().resolve_path( + match self.cm_mut().resolve_path( &segments, None, parent_scope, diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index cbc84540fcdef..212629395c98b 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -782,7 +782,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// This takes the error provided, combines it with the span and any additional spans inside the /// error and emits it. pub(crate) fn report_error( - &mut self, + &self, span: Span, resolution_error: ResolutionError<'ra>, ) -> ErrorGuaranteed { @@ -790,7 +790,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn into_struct_error( - &mut self, + &self, span: Span, resolution_error: ResolutionError<'ra>, ) -> Diag<'_> { @@ -1459,7 +1459,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn add_scope_set_candidates( - &mut self, + &self, suggestions: &mut Vec, scope_set: ScopeSet<'ra>, ps: &ParentScope<'ra>, @@ -1560,7 +1560,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( - &mut self, + &self, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, ident: Ident, @@ -1828,7 +1828,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// N.B., the method does not look into imports, but this is not a problem, /// since we report the definitions (thus, the de-aliased imports). pub(crate) fn lookup_import_candidates( - &mut self, + &self, lookup_ident: Ident, namespace: Namespace, parent_scope: &ParentScope<'ra>, @@ -3310,7 +3310,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// ``` #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_self_suggestion( - &mut self, + &self, mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { @@ -3330,7 +3330,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// ``` #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_crate_suggestion( - &mut self, + &self, mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { @@ -3362,7 +3362,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// ``` #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_super_suggestion( - &mut self, + &self, mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { @@ -3385,7 +3385,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// name as the first part of path. #[instrument(level = "debug", skip(self, parent_scope))] fn make_external_crate_suggestion( - &mut self, + &self, mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1c94779a6009a..3f34af1d01d83 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -346,7 +346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { diag_metadata, ))); } else if let RibKind::Block(Some(module)) = rib.kind - && let Ok(binding) = self.cm().resolve_ident_in_scope_set( + && let Ok(binding) = self.cm_mut().resolve_ident_in_scope_set( ident, ScopeSet::Module(ns, module.to_module()), parent_scope, @@ -362,7 +362,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let parent_scope = &ParentScope { module: module.to_module(), ..*parent_scope }; let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f }); return self - .cm() + .cm_mut() .resolve_ident_in_scope_set( orig_ident, ScopeSet::All(ns), @@ -1457,7 +1457,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Validate a local resolution (from ribs). #[instrument(level = "debug", skip(self, all_ribs))] fn validate_res_from_ribs( - &mut self, + &self, rib_index: usize, rib_ident: Ident, res: Res, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3f2e24995deab..c00eb97f4c3d6 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -34,9 +34,9 @@ use crate::diagnostics::{ }; use crate::ref_mut::{CmCell, CmRefCell}; use crate::{ - AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, - PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, + AmbiguityError, BindingKey, Decl, DeclData, DeclKind, Determinacy, Finalize, IdentKey, + ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult, + PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, }; @@ -735,7 +735,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let dummy_decl = self.dummy_decl; let dummy_decl = self.new_import_decl(dummy_decl, import); - self.per_ns(|this, ns| { + self.per_ns_mut(|this, ns| { let ident = IdentKey::new(target); // This can fail, dummies are inserted only in non-occupied slots. let _ = this.try_plant_decl_into_local_module(ident, target.span, ns, dummy_decl); @@ -782,13 +782,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut imports_to_resolve = mem::take(&mut self.indeterminate_imports); self.assert_speculative = true; - let cm_resolver = self.cm(); - rustc_data_structures::sync::par_for_each_slice( &mut imports_to_resolve, |(import, resolution, indeterminate_count)| { - (*resolution, *indeterminate_count) = - cm_resolver.reborrow_ref().resolve_import(*import); + (*resolution, *indeterminate_count) = self.resolve_import(*import); }, ); self.assert_speculative = false; @@ -835,7 +832,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ImportKind::Single { target, decls, .. }, ImportResolutionKind::Single(import_decls), ) => { - self.per_ns(|this, ns| { + self.per_ns_mut(|this, ns| { match import_decls[ns] { PendingDecl::Ready(Some(decl)) => { // We need the `target`, `source` can be extracted. @@ -1116,10 +1113,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// - Other values mean that indeterminate exists under certain namespaces. /// /// Meanwhile, if resolution is successful, its result is returned. - fn resolve_import<'r>( - mut self: CmResolver<'r, 'ra, 'tcx>, - import: Import<'ra>, - ) -> (Option>, usize) { + fn resolve_import(&self, import: Import<'ra>) -> (Option>, usize) { debug!( "(resolving import for module) resolving import `{}::{}` in `{}`", Segment::names_to_string(&import.module_path), @@ -1129,7 +1123,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = if let Some(module) = import.imported_module.get() { module } else { - let path_res = self.reborrow().maybe_resolve_path( + let path_res = self.cm().maybe_resolve_path( &import.module_path, None, &import.parent_scope, @@ -1157,11 +1151,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut decls = PerNS::default(); let mut indeterminate_count = 0; - self.per_ns_cm(|mut this, ns| { + self.per_ns(|this, ns| { if bindings[ns].get() != PendingDecl::Pending { return; }; - let binding_result = this.reborrow().maybe_resolve_ident_in_module( + let binding_result = this.cm().maybe_resolve_ident_in_module( module, source, ns, @@ -1202,7 +1196,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We'll provide more context to the privacy errors later, up to `len`. let privacy_errors_len = self.privacy_errors.len(); - let path_res = self.cm().resolve_path( + let path_res = self.cm_mut().resolve_path( &import.module_path, None, &import.parent_scope, @@ -1370,14 +1364,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // importing it if available. let mut path = import.module_path.clone(); path.push(Segment::from_ident(ident)); - if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.cm().resolve_path( - &path, - None, - &import.parent_scope, - Some(finalize), - ignore_decl, - None, - ) { + if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self + .cm_mut() + .resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_decl, None) + { let res = module.res().map(|r| (r, ident)); for error in &mut self.privacy_errors[privacy_errors_len..] { error.outermost_res = res; @@ -1407,8 +1397,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let mut all_ns_err = true; - self.per_ns(|this, ns| { - let binding = this.cm().resolve_ident_in_module( + self.per_ns_mut(|this, ns| { + let binding = this.cm_mut().resolve_ident_in_module( module, ident, ns, @@ -1472,8 +1462,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if all_ns_err { let mut all_ns_failed = true; - self.per_ns(|this, ns| { - let binding = this.cm().resolve_ident_in_module( + self.per_ns_mut(|this, ns| { + let binding = this.cm_mut().resolve_ident_in_module( module, ident, ns, @@ -1632,7 +1622,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(ident)); - self.per_ns(|this, ns| { + self.per_ns_mut(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding)); } @@ -1642,7 +1632,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - self.per_ns(|this, ns| { + self.per_ns_mut(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { this.owners.get_mut(&import_id).unwrap().import_res[ns] = Some(binding.res()); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 535d11d00d718..f30e6844c861c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1581,7 +1581,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { finalize: Option, source: PathSource<'_, 'ast, 'ra>, ) -> PathResult<'ra> { - self.r.cm().resolve_path_with_ribs( + self.r.cm_mut().resolve_path_with_ribs( path, opt_ns, &self.parent_scope, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e26bfa6b96d51..f2ce21377acce 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2067,7 +2067,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn update_err_for_private_tuple_struct_fields( - &mut self, + &self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>, def_id: DefId, @@ -2177,7 +2177,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| { + let bad_struct_syntax_suggestion = |this: &Self, err: &mut Diag<'_>, def_id: DefId| { let (followed_by_brace, closing_brace) = this.followed_by_brace(span); match source { @@ -2629,7 +2629,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn suggest_alternative_construction_methods( - &mut self, + &self, def_id: DefId, err: &mut Diag<'_>, path_span: Span, @@ -2784,7 +2784,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } fn lookup_assoc_candidate( - &mut self, + &self, ident: Ident, ns: Namespace, filter_fn: FilterFn, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2dbf32dc20288..e3365ed9ca0c8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1990,27 +1990,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Returns a conditionally mutable resolver. - /// - /// Currently only dependent on `assert_speculative`, if `assert_speculative` is false, - /// the resolver will allow mutation; otherwise, it will be immutable. - fn cm(&mut self) -> CmResolver<'_, 'ra, 'tcx> { - CmResolver::new(self, !self.assert_speculative) + /// Returns a conditionally mutable resolver that cannot be mutated. + fn cm(&self) -> CmResolver<'_, 'ra, 'tcx> { + CmResolver::Ref(self) + } + + /// Returns a conditionally mutable resolver that can be mutated. + /// Will panic if the `assert_speculative` field is true. + fn cm_mut(&mut self) -> CmResolver<'_, 'ra, 'tcx> { + assert!(!self.assert_speculative, "can't mutably borrow speculative resolver"); + CmResolver::Mut(self) } /// Runs the function on each namespace. - fn per_ns(&mut self, mut f: F) { + fn per_ns(&self, mut f: F) { f(self, TypeNS); f(self, ValueNS); f(self, MacroNS); } - fn per_ns_cm<'r, F: FnMut(CmResolver<'_, 'ra, 'tcx>, Namespace)>( - mut self: CmResolver<'r, 'ra, 'tcx>, - mut f: F, - ) { - f(self.reborrow(), TypeNS); - f(self.reborrow(), ValueNS); + fn per_ns_mut(&mut self, mut f: F) { + f(self, TypeNS); + f(self, ValueNS); f(self, MacroNS); } @@ -2080,7 +2081,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let scope_set = ScopeSet::All(TypeNS); let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); - self.cm().visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| { + let cmr = self.cm_mut(); + cmr.visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| { match scope { Scope::ModuleNonGlobs(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); @@ -2464,7 +2466,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, /// just that an error occurred. fn resolve_rustdoc_path( - &mut self, + &self, path_str: &str, ns: Namespace, parent_scope: ParentScope<'ra>, @@ -2791,7 +2793,7 @@ pub fn provide(providers: &mut Providers) { /// /// `Cm` stands for "conditionally mutable". /// -/// Prefer constructing it through [`Resolver::cm`] to ensure correctness. +/// Prefer constructing it through `Resolver::cm(_mut)` to ensure correctness. type CmResolver<'r, 'ra, 'tcx> = ref_mut::RefOrMut<'r, Resolver<'ra, 'tcx>>; // FIXME: These are cells for caches that can be populated even during speculative resolution, @@ -2802,68 +2804,52 @@ use std::cell::{Cell as CacheCell, RefCell as CacheRefCell}; mod ref_mut { use std::cell::{BorrowMutError, Cell, Ref, RefCell, RefMut}; use std::fmt; - use std::marker::PhantomData; use std::ops::Deref; use crate::Resolver; - /// A wrapper around a mutable reference that conditionally allows mutable access. - pub(crate) struct RefOrMut<'a, T> { - // We keep a raw pointer because it makes `reborrow_ref` possible. It is always safe to - // cast this to a `&T` because `RefOrMut` is only created through `new` which takes - // a `&mut T`. - p: *mut T, - mutable: bool, - _marker: PhantomData<&'a mut T>, + /// A reference type that conditionally allows mutable access. + pub(crate) enum RefOrMut<'a, T> { + Ref(&'a T), + Mut(&'a mut T), } impl<'a, T> Deref for RefOrMut<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { - // SAFETY: `RefOrMUt` is only constructable through a `&mut T`. - unsafe { self.p.as_ref_unchecked() } + match self { + RefOrMut::Ref(r) => r, + RefOrMut::Mut(r) => r, + } } } impl<'a, T> AsRef for RefOrMut<'a, T> { fn as_ref(&self) -> &T { - // SAFETY: `RefOrMUt` is only constructable through a `&mut T`. - unsafe { self.p.as_ref_unchecked() } + &*self } } impl<'a, T> RefOrMut<'a, T> { - pub(crate) fn new(p: &'a mut T, mutable: bool) -> Self { - RefOrMut { p, mutable, _marker: PhantomData } - } - - pub(crate) fn reborrow_ref(&self) -> RefOrMut<'_, T> { - assert!( - !self.mutable, - "Tried to reborrow a mutable `RefOrMut` through shared reference." - ); - RefOrMut { p: self.p, mutable: self.mutable, _marker: PhantomData } - } - - /// This is needed because this wraps a `&mut T` and is therefore not `Copy`. + /// This is needed because the type may allow mutable access and is therefore not `Copy`. pub(crate) fn reborrow(&mut self) -> RefOrMut<'_, T> { - RefOrMut { p: self.p, mutable: self.mutable, _marker: PhantomData } + match self { + RefOrMut::Ref(r) => RefOrMut::Ref(r), + RefOrMut::Mut(r) => RefOrMut::Mut(r), + } } /// Returns a mutable reference to the inner value if allowed. /// /// # Panics /// - /// Panics if the `mutable` flag is false. + /// Panics if the wrapped reference is immutable. #[track_caller] pub(crate) fn get_mut(&mut self) -> &mut T { - match self.mutable { - false => panic!("can't mutably borrow speculative resolver"), - // SAFETY: - // - `RefOrMut` is only constructable through a `&mut T` and we - // have tested that it may indeed be used as a `&mut T` in this match. - true => unsafe { self.p.as_mut_unchecked() }, + match self { + RefOrMut::Ref(_) => panic!("can't mutably borrow an immutable reference"), + RefOrMut::Mut(r) => r, } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 54f9aa8e914ec..1e9d60ca21551 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -613,7 +613,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { invoc_in_mod_inert_attr: Option, suggestion_span: Option, ) -> Result<(&'ra Arc, Res), Indeterminate> { - let (ext, res) = match self.cm().resolve_macro_or_delegation_path( + let (ext, res) = match self.cm_mut().resolve_macro_or_delegation_path( path, kind, parent_scope, @@ -966,7 +966,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for seg in &mut path { seg.id = None; } - match self.cm().resolve_path( + match self.cm_mut().resolve_path( &path, Some(ns), &parent_scope, @@ -1063,7 +1063,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let macro_resolutions = self.single_segment_macro_resolutions.take(self); for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions { - match self.cm().resolve_ident_in_scope_set( + match self.cm_mut().resolve_ident_in_scope_set( ident, ScopeSet::Macro(kind), &parent_scope, @@ -1117,7 +1117,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let builtin_attrs = mem::take(&mut self.builtin_attrs); for (ident, parent_scope) in builtin_attrs { - let _ = self.cm().resolve_ident_in_scope_set( + let _ = self.cm_mut().resolve_ident_in_scope_set( ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, @@ -1295,7 +1295,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn path_accessible( - &mut self, + &self, expn_id: LocalExpnId, path: &ast::Path, namespaces: &[Namespace],