@@ -53,6 +53,7 @@ use ty::CanonicalTy;
53
53
use ty:: CanonicalPolyFnSig ;
54
54
use util:: nodemap:: { DefIdMap , DefIdSet , ItemLocalMap } ;
55
55
use util:: nodemap:: { FxHashMap , FxHashSet } ;
56
+ use rustc_data_structures:: interner:: HashInterner ;
56
57
use smallvec:: SmallVec ;
57
58
use rustc_data_structures:: stable_hasher:: { HashStable , hash_stable_hashmap,
58
59
StableHasher , StableHasherResult ,
@@ -113,7 +114,7 @@ pub struct GlobalArenas<'tcx> {
113
114
const_allocs : TypedArena < interpret:: Allocation > ,
114
115
}
115
116
116
- type InternedSet < ' tcx , T > = Lock < FxHashSet < Interned < ' tcx , T > > > ;
117
+ type InternedSet < ' tcx , T > = Lock < FxHashMap < Interned < ' tcx , T > , ( ) > > ;
117
118
118
119
pub struct CtxtInterners < ' tcx > {
119
120
/// The arena that types, regions, etc are allocated from
@@ -166,51 +167,39 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
166
167
// determine that all contents are in the global tcx.
167
168
// See comments on Lift for why we can't use that.
168
169
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
+ } ;
179
176
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
+ }
187
184
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
192
187
} 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
+ } ;
203
194
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
+ } ;
209
200
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
214
203
}
215
204
}
216
205
}
@@ -825,12 +814,9 @@ impl<'tcx> CommonTypes<'tcx> {
825
814
fn new ( interners : & CtxtInterners < ' tcx > ) -> CommonTypes < ' tcx > {
826
815
let mk = |sty| CtxtInterners :: intern_ty ( interners, interners, sty) ;
827
816
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
834
820
} ;
835
821
CommonTypes {
836
822
bool : mk ( Bool ) ,
@@ -950,14 +936,14 @@ pub struct GlobalCtxt<'tcx> {
950
936
/// Data layout specification for the current target.
951
937
pub data_layout : TargetDataLayout ,
952
938
953
- stability_interner : Lock < FxHashSet < & ' tcx attr:: Stability > > ,
939
+ stability_interner : Lock < FxHashMap < & ' tcx attr:: Stability , ( ) > > ,
954
940
955
941
/// Stores the value of constants (and deduplicates the actual memory)
956
- allocation_interner : Lock < FxHashSet < & ' tcx Allocation > > ,
942
+ allocation_interner : Lock < FxHashMap < & ' tcx Allocation , ( ) > > ,
957
943
958
944
pub alloc_map : Lock < interpret:: AllocMap < ' tcx , & ' tcx Allocation > > ,
959
945
960
- layout_interner : Lock < FxHashSet < & ' tcx LayoutDetails > > ,
946
+ layout_interner : Lock < FxHashMap < & ' tcx LayoutDetails , ( ) > > ,
961
947
962
948
/// A general purpose channel to throw data out the back towards LLVM worker
963
949
/// threads.
@@ -1040,16 +1026,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1040
1026
self ,
1041
1027
alloc : Allocation ,
1042
1028
) -> & ' 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
+ } )
1053
1032
}
1054
1033
1055
1034
/// Allocates a byte or string literal for `mir::interpret`, read-only
@@ -1061,29 +1040,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1061
1040
}
1062
1041
1063
1042
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
+ } )
1074
1046
}
1075
1047
1076
1048
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
+ } )
1087
1052
}
1088
1053
1089
1054
/// Returns a range of the start/end indices specified with the
@@ -2193,7 +2158,7 @@ macro_rules! sty_debug_print {
2193
2158
} ;
2194
2159
$( let mut $variant = total; ) *
2195
2160
2196
- for & Interned ( t) in tcx. interners. type_. borrow( ) . iter ( ) {
2161
+ for & Interned ( t) in tcx. interners. type_. borrow( ) . keys ( ) {
2197
2162
let variant = match t. sty {
2198
2163
ty:: Bool | ty:: Char | ty:: Int ( ..) | ty:: Uint ( ..) |
2199
2164
ty:: Float ( ..) | ty:: Str | ty:: Never => continue ,
@@ -2252,6 +2217,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
2252
2217
/// An entry in an interner.
2253
2218
struct Interned < ' tcx , T : ' tcx +?Sized > ( & ' tcx T ) ;
2254
2219
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
+
2255
2227
// NB: An Interned<Ty> compares and hashes as a sty.
2256
2228
impl < ' tcx > PartialEq for Interned < ' tcx , TyS < ' tcx > > {
2257
2229
fn eq ( & self , other : & Interned < ' tcx , TyS < ' tcx > > ) -> bool {
@@ -2372,37 +2344,28 @@ macro_rules! intern_method {
2372
2344
// determine that all contents are in the global tcx.
2373
2345
// See comments on Lift for why we can't use that.
2374
2346
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
2391
2358
} 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
2406
2369
}
2407
2370
}
2408
2371
}
0 commit comments