@@ -53,6 +53,7 @@ use ty::CanonicalTy;
5353use ty:: CanonicalPolyFnSig ;
5454use util:: nodemap:: { DefIdMap , DefIdSet , ItemLocalMap } ;
5555use util:: nodemap:: { FxHashMap , FxHashSet } ;
56+ use rustc_data_structures:: interner:: HashInterner ;
5657use smallvec:: SmallVec ;
5758use rustc_data_structures:: stable_hasher:: { HashStable , hash_stable_hashmap,
5859 StableHasher , StableHasherResult ,
@@ -113,7 +114,7 @@ pub struct GlobalArenas<'tcx> {
113114 const_allocs : TypedArena < interpret:: Allocation > ,
114115}
115116
116- type InternedSet < ' tcx , T > = Lock < FxHashSet < Interned < ' tcx , T > > > ;
117+ type InternedSet < ' tcx , T > = Lock < FxHashMap < Interned < ' tcx , T > , ( ) > > ;
117118
118119pub struct CtxtInterners < ' tcx > {
119120 /// The arena that types, regions, etc are allocated from
@@ -166,51 +167,39 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
166167 // determine that all contents are in the global tcx.
167168 // See comments on Lift for why we can't use that.
168169 if flags. flags . intersects ( ty:: TypeFlags :: KEEP_IN_LOCAL_TCX ) {
169- let mut interner = local. type_ . borrow_mut ( ) ;
170- if let Some ( & Interned ( ty) ) = interner. get ( & st) {
171- return ty;
172- }
173-
174- let ty_struct = TyS {
175- sty : st,
176- flags : flags. flags ,
177- outer_exclusive_binder : flags. outer_exclusive_binder ,
178- } ;
170+ local. type_ . borrow_mut ( ) . intern ( st, |st| {
171+ let ty_struct = TyS {
172+ sty : st,
173+ flags : flags. flags ,
174+ outer_exclusive_binder : flags. outer_exclusive_binder ,
175+ } ;
179176
180- // Make sure we don't end up with inference
181- // types/regions in the global interner
182- if local as * const _ as usize == global as * const _ as usize {
183- bug ! ( "Attempted to intern `{:?}` which contains \
184- inference types/regions in the global type context",
185- & ty_struct) ;
186- }
177+ // Make sure we don't end up with inference
178+ // types/regions in the global interner
179+ if local as * const _ as usize == global as * const _ as usize {
180+ bug ! ( "Attempted to intern `{:?}` which contains \
181+ inference types/regions in the global type context",
182+ & ty_struct) ;
183+ }
187184
188- // Don't be &mut TyS.
189- let ty: Ty < ' tcx > = local. arena . alloc ( ty_struct) ;
190- interner. insert ( Interned ( ty) ) ;
191- ty
185+ Interned ( local. arena . alloc ( ty_struct) )
186+ } ) . 0
192187 } else {
193- let mut interner = global. type_ . borrow_mut ( ) ;
194- if let Some ( & Interned ( ty) ) = interner. get ( & st) {
195- return ty;
196- }
197-
198- let ty_struct = TyS {
199- sty : st,
200- flags : flags. flags ,
201- outer_exclusive_binder : flags. outer_exclusive_binder ,
202- } ;
188+ global. type_ . borrow_mut ( ) . intern ( st, |st| {
189+ let ty_struct = TyS {
190+ sty : st,
191+ flags : flags. flags ,
192+ outer_exclusive_binder : flags. outer_exclusive_binder ,
193+ } ;
203194
204- // This is safe because all the types the ty_struct can point to
205- // already is in the global arena
206- let ty_struct: TyS < ' gcx > = unsafe {
207- mem:: transmute ( ty_struct)
208- } ;
195+ // This is safe because all the types the ty_struct can point to
196+ // already is in the global arena
197+ let ty_struct: TyS < ' gcx > = unsafe {
198+ mem:: transmute ( ty_struct)
199+ } ;
209200
210- // Don't be &mut TyS.
211- let ty: Ty < ' gcx > = global. arena . alloc ( ty_struct) ;
212- interner. insert ( Interned ( ty) ) ;
213- ty
201+ Interned ( global. arena . alloc ( ty_struct) )
202+ } ) . 0
214203 }
215204 }
216205}
@@ -825,12 +814,9 @@ impl<'tcx> CommonTypes<'tcx> {
825814 fn new ( interners : & CtxtInterners < ' tcx > ) -> CommonTypes < ' tcx > {
826815 let mk = |sty| CtxtInterners :: intern_ty ( interners, interners, sty) ;
827816 let mk_region = |r| {
828- if let Some ( r) = interners. region . borrow ( ) . get ( & r) {
829- return r. 0 ;
830- }
831- let r = interners. arena . alloc ( r) ;
832- interners. region . borrow_mut ( ) . insert ( Interned ( r) ) ;
833- & * r
817+ interners. region . borrow_mut ( ) . intern ( r, |r| {
818+ Interned ( interners. arena . alloc ( r) )
819+ } ) . 0
834820 } ;
835821 CommonTypes {
836822 bool : mk ( Bool ) ,
@@ -950,14 +936,14 @@ pub struct GlobalCtxt<'tcx> {
950936 /// Data layout specification for the current target.
951937 pub data_layout : TargetDataLayout ,
952938
953- stability_interner : Lock < FxHashSet < & ' tcx attr:: Stability > > ,
939+ stability_interner : Lock < FxHashMap < & ' tcx attr:: Stability , ( ) > > ,
954940
955941 /// Stores the value of constants (and deduplicates the actual memory)
956- allocation_interner : Lock < FxHashSet < & ' tcx Allocation > > ,
942+ allocation_interner : Lock < FxHashMap < & ' tcx Allocation , ( ) > > ,
957943
958944 pub alloc_map : Lock < interpret:: AllocMap < ' tcx , & ' tcx Allocation > > ,
959945
960- layout_interner : Lock < FxHashSet < & ' tcx LayoutDetails > > ,
946+ layout_interner : Lock < FxHashMap < & ' tcx LayoutDetails , ( ) > > ,
961947
962948 /// A general purpose channel to throw data out the back towards LLVM worker
963949 /// threads.
@@ -1040,16 +1026,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10401026 self ,
10411027 alloc : Allocation ,
10421028 ) -> & ' gcx Allocation {
1043- let allocs = & mut self . allocation_interner . borrow_mut ( ) ;
1044- if let Some ( alloc) = allocs. get ( & alloc) {
1045- return alloc;
1046- }
1047-
1048- let interned = self . global_arenas . const_allocs . alloc ( alloc) ;
1049- if let Some ( prev) = allocs. replace ( interned) { // insert into interner
1050- bug ! ( "Tried to overwrite interned Allocation: {:#?}" , prev)
1051- }
1052- interned
1029+ self . allocation_interner . borrow_mut ( ) . intern ( alloc, |alloc| {
1030+ self . global_arenas . const_allocs . alloc ( alloc)
1031+ } )
10531032 }
10541033
10551034 /// Allocates a byte or string literal for `mir::interpret`, read-only
@@ -1061,29 +1040,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10611040 }
10621041
10631042 pub fn intern_stability ( self , stab : attr:: Stability ) -> & ' gcx attr:: Stability {
1064- let mut stability_interner = self . stability_interner . borrow_mut ( ) ;
1065- if let Some ( st) = stability_interner. get ( & stab) {
1066- return st;
1067- }
1068-
1069- let interned = self . global_interners . arena . alloc ( stab) ;
1070- if let Some ( prev) = stability_interner. replace ( interned) {
1071- bug ! ( "Tried to overwrite interned Stability: {:?}" , prev)
1072- }
1073- interned
1043+ self . stability_interner . borrow_mut ( ) . intern ( stab, |stab| {
1044+ self . global_interners . arena . alloc ( stab)
1045+ } )
10741046 }
10751047
10761048 pub fn intern_layout ( self , layout : LayoutDetails ) -> & ' gcx LayoutDetails {
1077- let mut layout_interner = self . layout_interner . borrow_mut ( ) ;
1078- if let Some ( layout) = layout_interner. get ( & layout) {
1079- return layout;
1080- }
1081-
1082- let interned = self . global_arenas . layout . alloc ( layout) ;
1083- if let Some ( prev) = layout_interner. replace ( interned) {
1084- bug ! ( "Tried to overwrite interned Layout: {:?}" , prev)
1085- }
1086- interned
1049+ self . layout_interner . borrow_mut ( ) . intern ( layout, |layout| {
1050+ self . global_arenas . layout . alloc ( layout)
1051+ } )
10871052 }
10881053
10891054 /// Returns a range of the start/end indices specified with the
@@ -2193,7 +2158,7 @@ macro_rules! sty_debug_print {
21932158 } ;
21942159 $( let mut $variant = total; ) *
21952160
2196- for & Interned ( t) in tcx. interners. type_. borrow( ) . iter ( ) {
2161+ for & Interned ( t) in tcx. interners. type_. borrow( ) . keys ( ) {
21972162 let variant = match t. sty {
21982163 ty:: Bool | ty:: Char | ty:: Int ( ..) | ty:: Uint ( ..) |
21992164 ty:: Float ( ..) | ty:: Str | ty:: Never => continue ,
@@ -2252,6 +2217,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
22522217/// An entry in an interner.
22532218struct Interned < ' tcx , T : ' tcx +?Sized > ( & ' tcx T ) ;
22542219
2220+ impl < ' tcx , T : ' tcx +?Sized > Clone for Interned < ' tcx , T > {
2221+ fn clone ( & self ) -> Self {
2222+ Interned ( self . 0 )
2223+ }
2224+ }
2225+ impl < ' tcx , T : ' tcx +?Sized > Copy for Interned < ' tcx , T > { }
2226+
22552227// NB: An Interned<Ty> compares and hashes as a sty.
22562228impl < ' tcx > PartialEq for Interned < ' tcx , TyS < ' tcx > > {
22572229 fn eq ( & self , other : & Interned < ' tcx , TyS < ' tcx > > ) -> bool {
@@ -2372,37 +2344,28 @@ macro_rules! intern_method {
23722344 // determine that all contents are in the global tcx.
23732345 // See comments on Lift for why we can't use that.
23742346 if ( $keep_in_local_tcx) ( & v) {
2375- let mut interner = self . interners. $name. borrow_mut( ) ;
2376- if let Some ( & Interned ( v) ) = interner. get( key) {
2377- return v;
2378- }
2379-
2380- // Make sure we don't end up with inference
2381- // types/regions in the global tcx.
2382- if self . is_global( ) {
2383- bug!( "Attempted to intern `{:?}` which contains \
2384- inference types/regions in the global type context",
2385- v) ;
2386- }
2387-
2388- let i = $alloc_method( & self . interners. arena, v) ;
2389- interner. insert( Interned ( i) ) ;
2390- i
2347+ self . interners. $name. borrow_mut( ) . intern_ref( key, || {
2348+ // Make sure we don't end up with inference
2349+ // types/regions in the global tcx.
2350+ if self . is_global( ) {
2351+ bug!( "Attempted to intern `{:?}` which contains \
2352+ inference types/regions in the global type context",
2353+ v) ;
2354+ }
2355+
2356+ Interned ( $alloc_method( & self . interners. arena, v) )
2357+ } ) . 0
23912358 } else {
2392- let mut interner = self . global_interners. $name. borrow_mut( ) ;
2393- if let Some ( & Interned ( v) ) = interner. get( key) {
2394- return v;
2395- }
2396-
2397- // This transmutes $alloc<'tcx> to $alloc<'gcx>
2398- let v = unsafe {
2399- mem:: transmute( v)
2400- } ;
2401- let i: & $lt_tcx $ty = $alloc_method( & self . global_interners. arena, v) ;
2402- // Cast to 'gcx
2403- let i = unsafe { mem:: transmute( i) } ;
2404- interner. insert( Interned ( i) ) ;
2405- i
2359+ self . global_interners. $name. borrow_mut( ) . intern_ref( key, || {
2360+ // This transmutes $alloc<'tcx> to $alloc<'gcx>
2361+ let v = unsafe {
2362+ mem:: transmute( v)
2363+ } ;
2364+ let i: & $lt_tcx $ty = $alloc_method( & self . global_interners. arena, v) ;
2365+ // Cast to 'gcx
2366+ let i = unsafe { mem:: transmute( i) } ;
2367+ Interned ( i)
2368+ } ) . 0
24062369 }
24072370 }
24082371 }
0 commit comments