@@ -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
@@ -167,51 +168,39 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
167168 // determine that all contents are in the global tcx.
168169 // See comments on Lift for why we can't use that.
169170 if flags. flags . intersects ( ty:: TypeFlags :: KEEP_IN_LOCAL_TCX ) {
170- let mut interner = local. type_ . borrow_mut ( ) ;
171- if let Some ( & Interned ( ty) ) = interner. get ( & st) {
172- return ty;
173- }
174-
175- let ty_struct = TyS {
176- sty : st,
177- flags : flags. flags ,
178- outer_exclusive_binder : flags. outer_exclusive_binder ,
179- } ;
171+ local. type_ . borrow_mut ( ) . intern ( st, |st| {
172+ let ty_struct = TyS {
173+ sty : st,
174+ flags : flags. flags ,
175+ outer_exclusive_binder : flags. outer_exclusive_binder ,
176+ } ;
180177
181- // Make sure we don't end up with inference
182- // types/regions in the global interner
183- if local as * const _ as usize == global as * const _ as usize {
184- bug ! ( "Attempted to intern `{:?}` which contains \
185- inference types/regions in the global type context",
186- & ty_struct) ;
187- }
178+ // Make sure we don't end up with inference
179+ // types/regions in the global interner
180+ if local as * const _ as usize == global as * const _ as usize {
181+ bug ! ( "Attempted to intern `{:?}` which contains \
182+ inference types/regions in the global type context",
183+ & ty_struct) ;
184+ }
188185
189- // Don't be &mut TyS.
190- let ty: Ty < ' tcx > = local. arena . alloc ( ty_struct) ;
191- interner. insert ( Interned ( ty) ) ;
192- ty
186+ Interned ( local. arena . alloc ( ty_struct) )
187+ } ) . 0
193188 } else {
194- let mut interner = global. type_ . borrow_mut ( ) ;
195- if let Some ( & Interned ( ty) ) = interner. get ( & st) {
196- return ty;
197- }
198-
199- let ty_struct = TyS {
200- sty : st,
201- flags : flags. flags ,
202- outer_exclusive_binder : flags. outer_exclusive_binder ,
203- } ;
189+ global. type_ . borrow_mut ( ) . intern ( st, |st| {
190+ let ty_struct = TyS {
191+ sty : st,
192+ flags : flags. flags ,
193+ outer_exclusive_binder : flags. outer_exclusive_binder ,
194+ } ;
204195
205- // This is safe because all the types the ty_struct can point to
206- // already is in the global arena
207- let ty_struct: TyS < ' gcx > = unsafe {
208- mem:: transmute ( ty_struct)
209- } ;
196+ // This is safe because all the types the ty_struct can point to
197+ // already is in the global arena
198+ let ty_struct: TyS < ' gcx > = unsafe {
199+ mem:: transmute ( ty_struct)
200+ } ;
210201
211- // Don't be &mut TyS.
212- let ty: Ty < ' gcx > = global. arena . alloc ( ty_struct) ;
213- interner. insert ( Interned ( ty) ) ;
214- ty
202+ Interned ( global. arena . alloc ( ty_struct) )
203+ } ) . 0
215204 }
216205 }
217206}
@@ -827,12 +816,9 @@ impl<'tcx> CommonTypes<'tcx> {
827816 fn new ( interners : & CtxtInterners < ' tcx > ) -> CommonTypes < ' tcx > {
828817 let mk = |sty| CtxtInterners :: intern_ty ( interners, interners, sty) ;
829818 let mk_region = |r| {
830- if let Some ( r) = interners. region . borrow ( ) . get ( & r) {
831- return r. 0 ;
832- }
833- let r = interners. arena . alloc ( r) ;
834- interners. region . borrow_mut ( ) . insert ( Interned ( r) ) ;
835- & * r
819+ interners. region . borrow_mut ( ) . intern ( r, |r| {
820+ Interned ( interners. arena . alloc ( r) )
821+ } ) . 0
836822 } ;
837823
838824 CommonTypes {
@@ -955,14 +941,14 @@ pub struct GlobalCtxt<'tcx> {
955941 /// Data layout specification for the current target.
956942 pub data_layout : TargetDataLayout ,
957943
958- stability_interner : Lock < FxHashSet < & ' tcx attr:: Stability > > ,
944+ stability_interner : Lock < FxHashMap < & ' tcx attr:: Stability , ( ) > > ,
959945
960946 /// Stores the value of constants (and deduplicates the actual memory)
961- allocation_interner : Lock < FxHashSet < & ' tcx Allocation > > ,
947+ allocation_interner : Lock < FxHashMap < & ' tcx Allocation , ( ) > > ,
962948
963949 pub alloc_map : Lock < interpret:: AllocMap < ' tcx , & ' tcx Allocation > > ,
964950
965- layout_interner : Lock < FxHashSet < & ' tcx LayoutDetails > > ,
951+ layout_interner : Lock < FxHashMap < & ' tcx LayoutDetails , ( ) > > ,
966952
967953 /// A general purpose channel to throw data out the back towards LLVM worker
968954 /// threads.
@@ -1045,16 +1031,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10451031 self ,
10461032 alloc : Allocation ,
10471033 ) -> & ' gcx Allocation {
1048- let allocs = & mut self . allocation_interner . borrow_mut ( ) ;
1049- if let Some ( alloc) = allocs. get ( & alloc) {
1050- return alloc;
1051- }
1052-
1053- let interned = self . global_arenas . const_allocs . alloc ( alloc) ;
1054- if let Some ( prev) = allocs. replace ( interned) { // insert into interner
1055- bug ! ( "Tried to overwrite interned Allocation: {:#?}" , prev)
1056- }
1057- interned
1034+ self . allocation_interner . borrow_mut ( ) . intern ( alloc, |alloc| {
1035+ self . global_arenas . const_allocs . alloc ( alloc)
1036+ } )
10581037 }
10591038
10601039 /// Allocates a byte or string literal for `mir::interpret`, read-only
@@ -1066,29 +1045,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10661045 }
10671046
10681047 pub fn intern_stability ( self , stab : attr:: Stability ) -> & ' gcx attr:: Stability {
1069- let mut stability_interner = self . stability_interner . borrow_mut ( ) ;
1070- if let Some ( st) = stability_interner. get ( & stab) {
1071- return st;
1072- }
1073-
1074- let interned = self . global_interners . arena . alloc ( stab) ;
1075- if let Some ( prev) = stability_interner. replace ( interned) {
1076- bug ! ( "Tried to overwrite interned Stability: {:?}" , prev)
1077- }
1078- interned
1048+ self . stability_interner . borrow_mut ( ) . intern ( stab, |stab| {
1049+ self . global_interners . arena . alloc ( stab)
1050+ } )
10791051 }
10801052
10811053 pub fn intern_layout ( self , layout : LayoutDetails ) -> & ' gcx LayoutDetails {
1082- let mut layout_interner = self . layout_interner . borrow_mut ( ) ;
1083- if let Some ( layout) = layout_interner. get ( & layout) {
1084- return layout;
1085- }
1086-
1087- let interned = self . global_arenas . layout . alloc ( layout) ;
1088- if let Some ( prev) = layout_interner. replace ( interned) {
1089- bug ! ( "Tried to overwrite interned Layout: {:?}" , prev)
1090- }
1091- interned
1054+ self . layout_interner . borrow_mut ( ) . intern ( layout, |layout| {
1055+ self . global_arenas . layout . alloc ( layout)
1056+ } )
10921057 }
10931058
10941059 /// Returns a range of the start/end indices specified with the
@@ -2198,7 +2163,7 @@ macro_rules! sty_debug_print {
21982163 } ;
21992164 $( let mut $variant = total; ) *
22002165
2201- for & Interned ( t) in tcx. interners. type_. borrow( ) . iter ( ) {
2166+ for & Interned ( t) in tcx. interners. type_. borrow( ) . keys ( ) {
22022167 let variant = match t. sty {
22032168 ty:: Bool | ty:: Char | ty:: Int ( ..) | ty:: Uint ( ..) |
22042169 ty:: Float ( ..) | ty:: Str | ty:: Never => continue ,
@@ -2257,6 +2222,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
22572222/// An entry in an interner.
22582223struct Interned < ' tcx , T : ' tcx +?Sized > ( & ' tcx T ) ;
22592224
2225+ impl < ' tcx , T : ' tcx +?Sized > Clone for Interned < ' tcx , T > {
2226+ fn clone ( & self ) -> Self {
2227+ Interned ( self . 0 )
2228+ }
2229+ }
2230+ impl < ' tcx , T : ' tcx +?Sized > Copy for Interned < ' tcx , T > { }
2231+
22602232// NB: An Interned<Ty> compares and hashes as a sty.
22612233impl < ' tcx > PartialEq for Interned < ' tcx , TyS < ' tcx > > {
22622234 fn eq ( & self , other : & Interned < ' tcx , TyS < ' tcx > > ) -> bool {
@@ -2377,37 +2349,28 @@ macro_rules! intern_method {
23772349 // determine that all contents are in the global tcx.
23782350 // See comments on Lift for why we can't use that.
23792351 if ( $keep_in_local_tcx) ( & v) {
2380- let mut interner = self . interners. $name. borrow_mut( ) ;
2381- if let Some ( & Interned ( v) ) = interner. get( key) {
2382- return v;
2383- }
2384-
2385- // Make sure we don't end up with inference
2386- // types/regions in the global tcx.
2387- if self . is_global( ) {
2388- bug!( "Attempted to intern `{:?}` which contains \
2389- inference types/regions in the global type context",
2390- v) ;
2391- }
2392-
2393- let i = $alloc_method( & self . interners. arena, v) ;
2394- interner. insert( Interned ( i) ) ;
2395- i
2352+ self . interners. $name. borrow_mut( ) . intern_ref( key, || {
2353+ // Make sure we don't end up with inference
2354+ // types/regions in the global tcx.
2355+ if self . is_global( ) {
2356+ bug!( "Attempted to intern `{:?}` which contains \
2357+ inference types/regions in the global type context",
2358+ v) ;
2359+ }
2360+
2361+ Interned ( $alloc_method( & self . interners. arena, v) )
2362+ } ) . 0
23962363 } else {
2397- let mut interner = self . global_interners. $name. borrow_mut( ) ;
2398- if let Some ( & Interned ( v) ) = interner. get( key) {
2399- return v;
2400- }
2401-
2402- // This transmutes $alloc<'tcx> to $alloc<'gcx>
2403- let v = unsafe {
2404- mem:: transmute( v)
2405- } ;
2406- let i: & $lt_tcx $ty = $alloc_method( & self . global_interners. arena, v) ;
2407- // Cast to 'gcx
2408- let i = unsafe { mem:: transmute( i) } ;
2409- interner. insert( Interned ( i) ) ;
2410- i
2364+ self . global_interners. $name. borrow_mut( ) . intern_ref( key, || {
2365+ // This transmutes $alloc<'tcx> to $alloc<'gcx>
2366+ let v = unsafe {
2367+ mem:: transmute( v)
2368+ } ;
2369+ let i: & $lt_tcx $ty = $alloc_method( & self . global_interners. arena, v) ;
2370+ // Cast to 'gcx
2371+ let i = unsafe { mem:: transmute( i) } ;
2372+ Interned ( i)
2373+ } ) . 0
24112374 }
24122375 }
24132376 }
0 commit comments