5
5
use rustc_arena:: DroplessArena ;
6
6
use rustc_data_structures:: fx:: FxHashMap ;
7
7
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , ToStableHashKey } ;
8
+ use rustc_data_structures:: sync:: Lock ;
8
9
use rustc_macros:: HashStable_Generic ;
9
10
use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
10
11
@@ -1696,6 +1697,9 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
1696
1697
}
1697
1698
}
1698
1699
1700
+ #[ derive( Default ) ]
1701
+ pub ( crate ) struct Interner ( Lock < InternerInner > ) ;
1702
+
1699
1703
// The `&'static str`s in this type actually point into the arena.
1700
1704
//
1701
1705
// The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
@@ -1705,45 +1709,46 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
1705
1709
// This type is private to prevent accidentally constructing more than one `Interner` on the same
1706
1710
// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
1707
1711
#[ derive( Default ) ]
1708
- pub ( crate ) struct Interner {
1712
+ struct InternerInner {
1709
1713
arena : DroplessArena ,
1710
1714
names : FxHashMap < & ' static str , Symbol > ,
1711
1715
strings : Vec < & ' static str > ,
1712
1716
}
1713
1717
1714
1718
impl Interner {
1715
1719
fn prefill ( init : & [ & ' static str ] ) -> Self {
1716
- Interner {
1720
+ Interner ( Lock :: new ( InternerInner {
1717
1721
strings : init. into ( ) ,
1718
1722
names : init. iter ( ) . copied ( ) . zip ( ( 0 ..) . map ( Symbol :: new) ) . collect ( ) ,
1719
1723
..Default :: default ( )
1720
- }
1724
+ } ) )
1721
1725
}
1722
1726
1723
1727
#[ 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) {
1726
1731
return name;
1727
1732
}
1728
1733
1729
- let name = Symbol :: new ( self . strings . len ( ) as u32 ) ;
1734
+ let name = Symbol :: new ( inner . strings . len ( ) as u32 ) ;
1730
1735
1731
1736
// `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
1732
1737
// UTF-8.
1733
1738
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 ( ) ) ) } ;
1735
1740
// It is safe to extend the arena allocation to `'static` because we only access
1736
1741
// these while the arena is still alive.
1737
1742
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) ;
1740
1745
name
1741
1746
}
1742
1747
1743
1748
// Get the symbol as a string. `Symbol::as_str()` should be used in
1744
1749
// 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 ( ) ]
1747
1752
}
1748
1753
}
1749
1754
@@ -1875,8 +1880,8 @@ impl Ident {
1875
1880
}
1876
1881
1877
1882
#[ 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 ) )
1880
1885
}
1881
1886
1882
1887
/// An alternative to [`Symbol`], useful when the chars within the symbol need to
0 commit comments