55use rustc_arena:: DroplessArena ;
66use rustc_data_structures:: fx:: FxHashMap ;
77use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , ToStableHashKey } ;
8+ use rustc_data_structures:: sync:: Lock ;
89use rustc_macros:: HashStable_Generic ;
910use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
1011
@@ -1696,6 +1697,9 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
16961697 }
16971698}
16981699
1700+ #[ derive( Default ) ]
1701+ pub ( crate ) struct Interner ( Lock < InternerInner > ) ;
1702+
16991703// The `&'static str`s in this type actually point into the arena.
17001704//
17011705// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
@@ -1705,45 +1709,46 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
17051709// This type is private to prevent accidentally constructing more than one `Interner` on the same
17061710// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
17071711#[ derive( Default ) ]
1708- pub ( crate ) struct Interner {
1712+ struct InternerInner {
17091713 arena : DroplessArena ,
17101714 names : FxHashMap < & ' static str , Symbol > ,
17111715 strings : Vec < & ' static str > ,
17121716}
17131717
17141718impl Interner {
17151719 fn prefill ( init : & [ & ' static str ] ) -> Self {
1716- Interner {
1720+ Interner ( Lock :: new ( InternerInner {
17171721 strings : init. into ( ) ,
17181722 names : init. iter ( ) . copied ( ) . zip ( ( 0 ..) . map ( Symbol :: new) ) . collect ( ) ,
17191723 ..Default :: default ( )
1720- }
1724+ } ) )
17211725 }
17221726
17231727 #[ inline]
1724- pub fn intern ( & mut self , string : & str ) -> Symbol {
1725- if let Some ( & name) = self . names . get ( string) {
1728+ pub ( crate ) fn intern ( & self , string : & str ) -> Symbol {
1729+ let mut inner = self . 0 . lock ( ) ;
1730+ if let Some ( & name) = inner. names . get ( string) {
17261731 return name;
17271732 }
17281733
1729- let name = Symbol :: new ( self . strings . len ( ) as u32 ) ;
1734+ let name = Symbol :: new ( inner . strings . len ( ) as u32 ) ;
17301735
17311736 // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
17321737 // UTF-8.
17331738 let string: & str =
1734- unsafe { str:: from_utf8_unchecked ( self . arena . alloc_slice ( string. as_bytes ( ) ) ) } ;
1739+ unsafe { str:: from_utf8_unchecked ( inner . arena . alloc_slice ( string. as_bytes ( ) ) ) } ;
17351740 // It is safe to extend the arena allocation to `'static` because we only access
17361741 // these while the arena is still alive.
17371742 let string: & ' static str = unsafe { & * ( string as * const str ) } ;
1738- self . strings . push ( string) ;
1739- self . names . insert ( string, name) ;
1743+ inner . strings . push ( string) ;
1744+ inner . names . insert ( string, name) ;
17401745 name
17411746 }
17421747
17431748 // Get the symbol as a string. `Symbol::as_str()` should be used in
17441749 // preference to this function.
1745- pub fn get ( & self , symbol : Symbol ) -> & str {
1746- self . strings [ symbol. 0 . as_usize ( ) ]
1750+ pub ( crate ) fn get ( & self , symbol : Symbol ) -> & str {
1751+ self . 0 . lock ( ) . strings [ symbol. 0 . as_usize ( ) ]
17471752 }
17481753}
17491754
@@ -1875,8 +1880,8 @@ impl Ident {
18751880}
18761881
18771882#[ inline]
1878- fn with_interner < T , F : FnOnce ( & mut Interner ) -> T > ( f : F ) -> T {
1879- with_session_globals ( |session_globals| f ( & mut * session_globals. symbol_interner . lock ( ) ) )
1883+ fn with_interner < T , F : FnOnce ( & Interner ) -> T > ( f : F ) -> T {
1884+ with_session_globals ( |session_globals| f ( & session_globals. symbol_interner ) )
18801885}
18811886
18821887/// An alternative to [`Symbol`], useful when the chars within the symbol need to
0 commit comments