2121#![ recursion_limit = "256" ]
2222// tidy-alphabetical-end
2323
24- use std:: cell:: Ref ;
24+ use std:: cell:: { Ref , RefMut } ;
2525use std:: collections:: BTreeSet ;
2626use std:: ops:: ControlFlow ;
2727use std:: sync:: { Arc , OnceLock } ;
@@ -81,7 +81,7 @@ use crate::diagnostics::impls::{
8181 ImportSuggestion , LabelSuggestion , OnUnknownData , StructCtor , Suggestion ,
8282} ;
8383use crate :: imports:: { ImportResolution , NameResolutionRef } ;
84- use crate :: ref_mut:: { CmCell , CmRefCell } ;
84+ use crate :: ref_mut:: { CmCell , CmRef , CmRefCell } ;
8585
8686mod build_reduced_graph;
8787mod check_unused;
@@ -637,7 +637,7 @@ type ResolutionTable<'ra> = FxIndexMap<BindingKey, NameResolutionRef<'ra>>;
637637
638638enum Resolutions < ' ra > {
639639 Local ( CmRefCell < ResolutionTable < ' ra > > ) ,
640- Extern ( OnceLock < CmRefCell < ResolutionTable < ' ra > > > ) ,
640+ Extern ( OnceLock < ResolutionTable < ' ra > > ) ,
641641}
642642
643643impl < ' ra > Resolutions < ' ra > {
@@ -792,7 +792,7 @@ impl<'ra> Module<'ra> {
792792 resolver : & R ,
793793 mut f : impl FnMut ( & R , IdentKey , Span , Namespace , Decl < ' ra > ) ,
794794 ) {
795- for ( key, name_resolution) in resolver. as_ref ( ) . resolutions ( self ) . borrow ( ) . iter ( ) {
795+ for ( key, name_resolution) in resolver. as_ref ( ) . resolutions ( self ) . iter ( ) {
796796 let name_resolution = name_resolution. borrow ( ) ;
797797 if let Some ( decl) = name_resolution. best_decl ( ) {
798798 f ( resolver, key. ident , name_resolution. orig_ident_span , key. ns , decl) ;
@@ -805,7 +805,7 @@ impl<'ra> Module<'ra> {
805805 resolver : & mut R ,
806806 mut f : impl FnMut ( & mut R , IdentKey , Span , Namespace , Decl < ' ra > ) ,
807807 ) {
808- for ( key, name_resolution) in resolver. as_mut ( ) . resolutions ( self ) . borrow ( ) . iter ( ) {
808+ for ( key, name_resolution) in resolver. as_mut ( ) . resolutions ( self ) . iter ( ) {
809809 let name_resolution = name_resolution. borrow ( ) ;
810810 if let Some ( decl) = name_resolution. best_decl ( ) {
811811 f ( resolver, key. ident , name_resolution. orig_ident_span , key. ns , decl) ;
@@ -2152,7 +2152,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
21522152 match ( trait_module, assoc_item) {
21532153 ( Some ( trait_module) , Some ( ( name, ns) ) ) => self
21542154 . resolutions ( trait_module)
2155- . borrow ( )
21562155 . iter ( )
21572156 . any ( |( key, _name_resolution) | key. ns == ns && key. ident . name == name) ,
21582157 _ => true ,
@@ -2177,14 +2176,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
21772176 self . tcx . hir_arena . alloc_slice ( & import_ids)
21782177 }
21792178
2180- fn resolutions ( & self , module : Module < ' ra > ) -> & ' ra CmRefCell < ResolutionTable < ' ra > > {
2179+ fn resolutions ( & self , module : Module < ' ra > ) -> CmRef < ' ra , ResolutionTable < ' ra > > {
21812180 match & module. 0 . 0 . lazy_resolutions {
2182- Resolutions :: Local ( local_res) => local_res,
2181+ Resolutions :: Local ( local_res) => CmRef :: Tracked ( local_res. borrow ( ) ) ,
21832182 Resolutions :: Extern ( extern_res) => {
2184- // as long as 1 thread is building this external table, all other threads will wait
2185- extern_res. get_or_init ( || {
2186- CmRefCell :: new ( self . build_reduced_graph_external ( module. expect_extern ( ) ) )
2187- } )
2183+ // It is fine to return a `CmRef::Untracked`, we never give out a `&mut`
2184+ // to an external table.
2185+ CmRef :: Untracked (
2186+ // As long as 1 thread is building this external table, all other threads will wait.
2187+ extern_res
2188+ . get_or_init ( || self . build_reduced_graph_external ( module. expect_extern ( ) ) ) ,
2189+ )
2190+ }
2191+ }
2192+ }
2193+
2194+ fn resolutions_mut ( & self , module : Module < ' ra > ) -> RefMut < ' ra , ResolutionTable < ' ra > > {
2195+ match & module. 0 . 0 . lazy_resolutions {
2196+ Resolutions :: Local ( local_res) => local_res. borrow_mut ( self ) ,
2197+ Resolutions :: Extern ( _) => {
2198+ // We do not allow in place mutations of the external resolution table. In fact,
2199+ // we never attempt it.
2200+ unreachable ! ( "Attempted to mutably borrow an extenral resolution table" )
21882201 }
21892202 }
21902203 }
@@ -2194,7 +2207,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
21942207 module : Module < ' ra > ,
21952208 key : BindingKey ,
21962209 ) -> Option < Ref < ' ra , NameResolution < ' ra > > > {
2197- self . resolutions ( module) . borrow ( ) . get ( & key) . map ( |resolution| resolution. 0 . borrow ( ) )
2210+ self . resolutions ( module) . get ( & key) . map ( |resolution| resolution. 0 . borrow ( ) )
21982211 }
21992212
22002213 #[ track_caller]
@@ -2204,7 +2217,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
22042217 key : BindingKey ,
22052218 orig_ident_span : Span ,
22062219 ) -> NameResolutionRef < ' ra > {
2207- * self . resolutions ( module) . borrow_mut ( self ) . entry ( key) . or_insert_with ( || {
2220+ * self . resolutions_mut ( module) . entry ( key) . or_insert_with ( || {
22082221 self . arenas . alloc_name_resolution ( NameResolution :: new ( orig_ident_span) )
22092222 } )
22102223 }
@@ -2915,6 +2928,24 @@ mod ref_mut {
29152928 }
29162929 }
29172930
2931+ pub ( crate ) enum CmRef < ' b , T > {
2932+ /// A tracked borrow of a [`CmRefCell`]
2933+ Tracked ( Ref < ' b , T > ) ,
2934+ /// An untracked or normal reference (not dynamically borrow-checked by `RefCell`)
2935+ Untracked ( & ' b T ) ,
2936+ }
2937+
2938+ impl < ' b , T > Deref for CmRef < ' b , T > {
2939+ type Target = T ;
2940+
2941+ fn deref ( & self ) -> & Self :: Target {
2942+ match self {
2943+ CmRef :: Tracked ( r) => r,
2944+ CmRef :: Untracked ( r) => r,
2945+ }
2946+ }
2947+ }
2948+
29182949 /// A wrapper around a [`RefCell`] that only allows writes (mutable borrows) based on a condition in the resolver.
29192950 #[ derive( Default ) ]
29202951 pub ( crate ) struct CmRefCell < T > ( RefCell < T > ) ;
@@ -2926,10 +2957,7 @@ mod ref_mut {
29262957
29272958 #[ track_caller]
29282959 pub ( crate ) fn borrow_mut < ' ra , ' tcx > ( & self , r : & Resolver < ' ra , ' tcx > ) -> RefMut < ' _ , T > {
2929- if r. assert_speculative {
2930- panic ! ( "not allowed to mutably borrow a `CmRefCell` during speculative resolution" ) ;
2931- }
2932- self . 0 . borrow_mut ( )
2960+ self . try_borrow_mut ( r) . unwrap ( )
29332961 }
29342962
29352963 #[ track_caller]
0 commit comments