@@ -472,7 +472,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>)
472
472
}
473
473
474
474
// Now we've done all our shifting. Return the value we grabbed earlier.
475
- ( retkey, retval, gap. into_bucket ( ) . into_table ( ) )
475
+ ( retkey, retval, gap. into_table ( ) )
476
476
}
477
477
478
478
/// Perform robin hood bucket stealing at the given `bucket`. You must
@@ -485,14 +485,14 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
485
485
mut key : K ,
486
486
mut val : V )
487
487
-> FullBucketMut < ' a , K , V > {
488
- let start_index = bucket. index ( ) ;
489
488
let size = bucket. table ( ) . size ( ) ;
490
- // Save the *starting point*.
491
- let mut bucket = bucket. stash ( ) ;
489
+ let raw_capacity = bucket. table ( ) . capacity ( ) ;
492
490
// There can be at most `size - dib` buckets to displace, because
493
491
// in the worst case, there are `size` elements and we already are
494
492
// `displacement` buckets away from the initial one.
495
- let idx_end = start_index + size - bucket. displacement ( ) ;
493
+ let idx_end = ( bucket. index ( ) + size - bucket. displacement ( ) ) % raw_capacity;
494
+ // Save the *starting point*.
495
+ let mut bucket = bucket. stash ( ) ;
496
496
497
497
loop {
498
498
let ( old_hash, old_key, old_val) = bucket. replace ( hash, key, val) ;
@@ -568,11 +568,8 @@ impl<K, V, S> HashMap<K, V, S>
568
568
// The caller should ensure that invariants by Robin Hood Hashing hold
569
569
// and that there's space in the underlying table.
570
570
fn insert_hashed_ordered ( & mut self , hash : SafeHash , k : K , v : V ) {
571
- let raw_cap = self . raw_capacity ( ) ;
572
571
let mut buckets = Bucket :: new ( & mut self . table , hash) ;
573
- // note that buckets.index() keeps increasing
574
- // even if the pointer wraps back to the first bucket.
575
- let limit_bucket = buckets. index ( ) + raw_cap;
572
+ let start_index = buckets. index ( ) ;
576
573
577
574
loop {
578
575
// We don't need to compare hashes for value swap.
@@ -585,7 +582,7 @@ impl<K, V, S> HashMap<K, V, S>
585
582
Full ( b) => b. into_bucket ( ) ,
586
583
} ;
587
584
buckets. next ( ) ;
588
- debug_assert ! ( buckets. index( ) < limit_bucket ) ;
585
+ debug_assert ! ( buckets. index( ) != start_index ) ;
589
586
}
590
587
}
591
588
}
@@ -1244,24 +1241,25 @@ impl<K, V, S> HashMap<K, V, S>
1244
1241
pub fn retain < F > ( & mut self , mut f : F )
1245
1242
where F : FnMut ( & K , & mut V ) -> bool
1246
1243
{
1247
- if self . table . capacity ( ) == 0 || self . table . size ( ) == 0 {
1244
+ if self . table . size ( ) == 0 {
1248
1245
return ;
1249
1246
}
1247
+ let mut elems_left = self . table . size ( ) ;
1250
1248
let mut bucket = Bucket :: head_bucket ( & mut self . table ) ;
1251
1249
bucket. prev ( ) ;
1252
- let tail = bucket. index ( ) ;
1253
- loop {
1250
+ let start_index = bucket. index ( ) ;
1251
+ while elems_left != 0 {
1254
1252
bucket = match bucket. peek ( ) {
1255
1253
Full ( mut full) => {
1254
+ elems_left -= 1 ;
1256
1255
let should_remove = {
1257
1256
let ( k, v) = full. read_mut ( ) ;
1258
1257
!f ( k, v)
1259
1258
} ;
1260
1259
if should_remove {
1261
- let prev_idx = full. index ( ) ;
1262
1260
let prev_raw = full. raw ( ) ;
1263
1261
let ( _, _, t) = pop_internal ( full) ;
1264
- Bucket :: new_from ( prev_raw, prev_idx , t)
1262
+ Bucket :: new_from ( prev_raw, t)
1265
1263
} else {
1266
1264
full. into_bucket ( )
1267
1265
}
@@ -1271,9 +1269,7 @@ impl<K, V, S> HashMap<K, V, S>
1271
1269
}
1272
1270
} ;
1273
1271
bucket. prev ( ) ; // reverse iteration
1274
- if bucket. index ( ) == tail {
1275
- break ;
1276
- }
1272
+ debug_assert ! ( elems_left == 0 || bucket. index( ) != start_index) ;
1277
1273
}
1278
1274
}
1279
1275
}
0 commit comments