@@ -1420,7 +1420,7 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
1420
1420
/// `RawIterHash` struct, we have to make the `iter_hash` method unsafe.
1421
1421
#[ cfg_attr( feature = "inline-more" , inline) ]
1422
1422
#[ cfg( feature = "raw" ) ]
1423
- pub unsafe fn iter_hash ( & self , hash : u64 ) -> RawIterHash < ' _ , T , A > {
1423
+ pub unsafe fn iter_hash ( & self , hash : u64 ) -> RawIterHash < T > {
1424
1424
RawIterHash :: new ( self , hash)
1425
1425
}
1426
1426
@@ -3203,13 +3203,28 @@ impl<T, A: Allocator + Clone> FusedIterator for RawDrain<'_, T, A> {}
3203
3203
/// `RawTable` only stores 7 bits of the hash value, so this iterator may return
3204
3204
/// items that have a hash value different than the one provided. You should
3205
3205
/// always validate the returned values before using them.
3206
- pub struct RawIterHash < ' a , T , A : Allocator + Clone = Global > {
3207
- inner : RawIterHashInner < ' a , A > ,
3206
+ ///
3207
+ /// For maximum flexibility this iterator is not bound by a lifetime, but you
3208
+ /// must observe several rules when using it:
3209
+ /// - You must not free the hash table while iterating (including via growing/shrinking).
3210
+ /// - It is fine to erase a bucket that has been yielded by the iterator.
3211
+ /// - Erasing a bucket that has not yet been yielded by the iterator may still
3212
+ /// result in the iterator yielding that bucket.
3213
+ /// - It is unspecified whether an element inserted after the iterator was
3214
+ /// created will be yielded by that iterator.
3215
+ /// - The order in which the iterator yields buckets is unspecified and may
3216
+ /// change in the future.
3217
+ pub struct RawIterHash < T > {
3218
+ inner : RawIterHashInner ,
3208
3219
_marker : PhantomData < T > ,
3209
3220
}
3210
3221
3211
- struct RawIterHashInner < ' a , A : Allocator + Clone > {
3212
- table : & ' a RawTableInner < A > ,
3222
+ struct RawIterHashInner {
3223
+ // See `RawTableInner`'s corresponding fields for details.
3224
+ // We can't store a `*const RawTableInner` as it would get
3225
+ // invalidated by the user calling `&mut` methods on `RawTable`.
3226
+ bucket_mask : usize ,
3227
+ ctrl : NonNull < u8 > ,
3213
3228
3214
3229
// The top 7 bits of the hash.
3215
3230
h2_hash : u8 ,
@@ -3223,65 +3238,77 @@ struct RawIterHashInner<'a, A: Allocator + Clone> {
3223
3238
bitmask : BitMaskIter ,
3224
3239
}
3225
3240
3226
- impl < ' a , T , A : Allocator + Clone > RawIterHash < ' a , T , A > {
3241
+ impl < T > RawIterHash < T > {
3227
3242
#[ cfg_attr( feature = "inline-more" , inline) ]
3228
3243
#[ cfg( feature = "raw" ) ]
3229
- fn new ( table : & ' a RawTable < T , A > , hash : u64 ) -> Self {
3244
+ unsafe fn new < A : Allocator + Clone > ( table : & RawTable < T , A > , hash : u64 ) -> Self {
3230
3245
RawIterHash {
3231
3246
inner : RawIterHashInner :: new ( & table. table , hash) ,
3232
3247
_marker : PhantomData ,
3233
3248
}
3234
3249
}
3235
3250
}
3236
- impl < ' a , A : Allocator + Clone > RawIterHashInner < ' a , A > {
3251
+ impl RawIterHashInner {
3237
3252
#[ cfg_attr( feature = "inline-more" , inline) ]
3238
3253
#[ cfg( feature = "raw" ) ]
3239
- fn new ( table : & ' a RawTableInner < A > , hash : u64 ) -> Self {
3240
- unsafe {
3241
- let h2_hash = h2 ( hash) ;
3242
- let probe_seq = table. probe_seq ( hash) ;
3243
- let group = Group :: load ( table. ctrl ( probe_seq. pos ) ) ;
3244
- let bitmask = group. match_byte ( h2_hash) . into_iter ( ) ;
3245
-
3246
- RawIterHashInner {
3247
- table,
3248
- h2_hash,
3249
- probe_seq,
3250
- group,
3251
- bitmask,
3252
- }
3254
+ unsafe fn new < A : Allocator + Clone > ( table : & RawTableInner < A > , hash : u64 ) -> Self {
3255
+ let h2_hash = h2 ( hash) ;
3256
+ let probe_seq = table. probe_seq ( hash) ;
3257
+ let group = Group :: load ( table. ctrl ( probe_seq. pos ) ) ;
3258
+ let bitmask = group. match_byte ( h2_hash) . into_iter ( ) ;
3259
+
3260
+ RawIterHashInner {
3261
+ bucket_mask : table. bucket_mask ,
3262
+ ctrl : table. ctrl ,
3263
+ h2_hash,
3264
+ probe_seq,
3265
+ group,
3266
+ bitmask,
3253
3267
}
3254
3268
}
3255
3269
}
3256
3270
3257
- impl < ' a , T , A : Allocator + Clone > Iterator for RawIterHash < ' a , T , A > {
3271
+ impl < T > Iterator for RawIterHash < T > {
3258
3272
type Item = Bucket < T > ;
3259
3273
3260
3274
fn next ( & mut self ) -> Option < Bucket < T > > {
3261
3275
unsafe {
3262
3276
match self . inner . next ( ) {
3263
- Some ( index) => Some ( self . inner . table . bucket ( index) ) ,
3277
+ Some ( index) => {
3278
+ // Can't use `RawTable::bucket` here as we don't have
3279
+ // an actual `RawTable` reference to use.
3280
+ debug_assert ! ( index <= self . inner. bucket_mask) ;
3281
+ let bucket = Bucket :: from_base_index ( self . inner . ctrl . cast ( ) , index) ;
3282
+ Some ( bucket)
3283
+ }
3264
3284
None => None ,
3265
3285
}
3266
3286
}
3267
3287
}
3268
3288
}
3269
3289
3270
- impl < ' a , A : Allocator + Clone > Iterator for RawIterHashInner < ' a , A > {
3290
+ impl Iterator for RawIterHashInner {
3271
3291
type Item = usize ;
3272
3292
3273
3293
fn next ( & mut self ) -> Option < Self :: Item > {
3274
3294
unsafe {
3275
3295
loop {
3276
3296
if let Some ( bit) = self . bitmask . next ( ) {
3277
- let index = ( self . probe_seq . pos + bit) & self . table . bucket_mask ;
3297
+ let index = ( self . probe_seq . pos + bit) & self . bucket_mask ;
3278
3298
return Some ( index) ;
3279
3299
}
3280
3300
if likely ( self . group . match_empty ( ) . any_bit_set ( ) ) {
3281
3301
return None ;
3282
3302
}
3283
- self . probe_seq . move_next ( self . table . bucket_mask ) ;
3284
- self . group = Group :: load ( self . table . ctrl ( self . probe_seq . pos ) ) ;
3303
+ self . probe_seq . move_next ( self . bucket_mask ) ;
3304
+
3305
+ // Can't use `RawTableInner::ctrl` here as we don't have
3306
+ // an actual `RawTableInner` reference to use.
3307
+ let index = self . probe_seq . pos ;
3308
+ debug_assert ! ( index < self . bucket_mask + 1 + Group :: WIDTH ) ;
3309
+ let group_ctrl = self . ctrl . as_ptr ( ) . add ( index) ;
3310
+
3311
+ self . group = Group :: load ( group_ctrl) ;
3285
3312
self . bitmask = self . group . match_byte ( self . h2_hash ) . into_iter ( ) ;
3286
3313
}
3287
3314
}
0 commit comments