@@ -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
@@ -167,51 +168,39 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
167
168
// determine that all contents are in the global tcx.
168
169
// See comments on Lift for why we can't use that.
169
170
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
+ } ;
180
177
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
+ }
188
185
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
193
188
} 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
+ } ;
204
195
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
+ } ;
210
201
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
215
204
}
216
205
}
217
206
}
@@ -827,12 +816,9 @@ impl<'tcx> CommonTypes<'tcx> {
827
816
fn new ( interners : & CtxtInterners < ' tcx > ) -> CommonTypes < ' tcx > {
828
817
let mk = |sty| CtxtInterners :: intern_ty ( interners, interners, sty) ;
829
818
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
836
822
} ;
837
823
838
824
CommonTypes {
@@ -955,14 +941,14 @@ pub struct GlobalCtxt<'tcx> {
955
941
/// Data layout specification for the current target.
956
942
pub data_layout : TargetDataLayout ,
957
943
958
- stability_interner : Lock < FxHashSet < & ' tcx attr:: Stability > > ,
944
+ stability_interner : Lock < FxHashMap < & ' tcx attr:: Stability , ( ) > > ,
959
945
960
946
/// Stores the value of constants (and deduplicates the actual memory)
961
- allocation_interner : Lock < FxHashSet < & ' tcx Allocation > > ,
947
+ allocation_interner : Lock < FxHashMap < & ' tcx Allocation , ( ) > > ,
962
948
963
949
pub alloc_map : Lock < interpret:: AllocMap < ' tcx , & ' tcx Allocation > > ,
964
950
965
- layout_interner : Lock < FxHashSet < & ' tcx LayoutDetails > > ,
951
+ layout_interner : Lock < FxHashMap < & ' tcx LayoutDetails , ( ) > > ,
966
952
967
953
/// A general purpose channel to throw data out the back towards LLVM worker
968
954
/// threads.
@@ -1045,16 +1031,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1045
1031
self ,
1046
1032
alloc : Allocation ,
1047
1033
) -> & ' 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
+ } )
1058
1037
}
1059
1038
1060
1039
/// Allocates a byte or string literal for `mir::interpret`, read-only
@@ -1066,29 +1045,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1066
1045
}
1067
1046
1068
1047
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
+ } )
1079
1051
}
1080
1052
1081
1053
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
+ } )
1092
1057
}
1093
1058
1094
1059
/// Returns a range of the start/end indices specified with the
@@ -2198,7 +2163,7 @@ macro_rules! sty_debug_print {
2198
2163
} ;
2199
2164
$( let mut $variant = total; ) *
2200
2165
2201
- for & Interned ( t) in tcx. interners. type_. borrow( ) . iter ( ) {
2166
+ for & Interned ( t) in tcx. interners. type_. borrow( ) . keys ( ) {
2202
2167
let variant = match t. sty {
2203
2168
ty:: Bool | ty:: Char | ty:: Int ( ..) | ty:: Uint ( ..) |
2204
2169
ty:: Float ( ..) | ty:: Str | ty:: Never => continue ,
@@ -2257,6 +2222,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
2257
2222
/// An entry in an interner.
2258
2223
struct Interned < ' tcx , T : ' tcx +?Sized > ( & ' tcx T ) ;
2259
2224
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
+
2260
2232
// NB: An Interned<Ty> compares and hashes as a sty.
2261
2233
impl < ' tcx > PartialEq for Interned < ' tcx , TyS < ' tcx > > {
2262
2234
fn eq ( & self , other : & Interned < ' tcx , TyS < ' tcx > > ) -> bool {
@@ -2377,37 +2349,28 @@ macro_rules! intern_method {
2377
2349
// determine that all contents are in the global tcx.
2378
2350
// See comments on Lift for why we can't use that.
2379
2351
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
2396
2363
} 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
2411
2374
}
2412
2375
}
2413
2376
}
0 commit comments