@@ -371,9 +371,9 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
371371 return InternalEntry :: TableIsEmpty ;
372372 }
373373
374- let size = table. size ( ) as isize ;
374+ let size = table. size ( ) ;
375375 let mut probe = Bucket :: new ( table, hash) ;
376- let ib = probe . index ( ) as isize ;
376+ let mut displacement = 0 ;
377377
378378 loop {
379379 let full = match probe. peek ( ) {
@@ -387,15 +387,15 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
387387 Full ( bucket) => bucket,
388388 } ;
389389
390- let robin_ib = full. index ( ) as isize - full . displacement ( ) as isize ;
390+ let probe_displacement = full. displacement ( ) ;
391391
392- if ib < robin_ib {
392+ if probe_displacement < displacement {
393393 // Found a luckier bucket than me.
394394 // We can finish the search early if we hit any bucket
395395 // with a lower distance to initial bucket than we've probed.
396396 return InternalEntry :: Vacant {
397397 hash : hash,
398- elem : NeqElem ( full, robin_ib as usize ) ,
398+ elem : NeqElem ( full, probe_displacement ) ,
399399 } ;
400400 }
401401
@@ -406,9 +406,9 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
406406 return InternalEntry :: Occupied { elem : full } ;
407407 }
408408 }
409-
409+ displacement += 1 ;
410410 probe = full. next ( ) ;
411- debug_assert ! ( probe . index ( ) as isize != ib + size + 1 ) ;
411+ debug_assert ! ( displacement <= size) ;
412412 }
413413}
414414
@@ -431,12 +431,11 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
431431}
432432
433433/// Perform robin hood bucket stealing at the given `bucket`. You must
434- /// also pass the position of that bucket's initial bucket so we don't have
435- /// to recalculate it.
434+ /// also pass that bucket's displacement so we don't have to recalculate it.
436435///
437436/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
438437fn robin_hood < ' a , K : ' a , V : ' a > ( bucket : FullBucketMut < ' a , K , V > ,
439- mut ib : usize ,
438+ mut displacement : usize ,
440439 mut hash : SafeHash ,
441440 mut key : K ,
442441 mut val : V )
@@ -457,6 +456,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
457456 val = old_val;
458457
459458 loop {
459+ displacement += 1 ;
460460 let probe = bucket. next ( ) ;
461461 debug_assert ! ( probe. index( ) != idx_end) ;
462462
@@ -476,13 +476,13 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
476476 Full ( bucket) => bucket,
477477 } ;
478478
479- let probe_ib = full_bucket . index ( ) - full_bucket. displacement ( ) ;
479+ let probe_displacement = full_bucket. displacement ( ) ;
480480
481481 bucket = full_bucket;
482482
483483 // Robin hood! Steal the spot.
484- if ib < probe_ib {
485- ib = probe_ib ;
484+ if probe_displacement < displacement {
485+ displacement = probe_displacement ;
486486 break ;
487487 }
488488 }
@@ -520,13 +520,16 @@ impl<K, V, S> HashMap<K, V, S>
520520 search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
521521 }
522522
523- // The caller should ensure that invariants by Robin Hood Hashing hold.
523+ // The caller should ensure that invariants by Robin Hood Hashing hold
524+ // and that there's space in the underlying table.
524525 fn insert_hashed_ordered ( & mut self , hash : SafeHash , k : K , v : V ) {
525526 let raw_cap = self . raw_capacity ( ) ;
526527 let mut buckets = Bucket :: new ( & mut self . table , hash) ;
527- let ib = buckets. index ( ) ;
528+ // note that buckets.index() keeps increasing
529+ // even if the pointer wraps back to the first bucket.
530+ let limit_bucket = buckets. index ( ) + raw_cap;
528531
529- while buckets . index ( ) != ib + raw_cap {
532+ loop {
530533 // We don't need to compare hashes for value swap.
531534 // Not even DIBs for Robin Hood.
532535 buckets = match buckets. peek ( ) {
@@ -537,8 +540,8 @@ impl<K, V, S> HashMap<K, V, S>
537540 Full ( b) => b. into_bucket ( ) ,
538541 } ;
539542 buckets. next ( ) ;
543+ debug_assert ! ( buckets. index( ) < limit_bucket) ;
540544 }
541- panic ! ( "Internal HashMap error: Out of space." ) ;
542545 }
543546}
544547
@@ -1959,7 +1962,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
19591962 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
19601963 pub fn insert ( self , value : V ) -> & ' a mut V {
19611964 match self . elem {
1962- NeqElem ( bucket, ib ) => robin_hood ( bucket, ib , self . hash , self . key , value) ,
1965+ NeqElem ( bucket, disp ) => robin_hood ( bucket, disp , self . hash , self . key , value) ,
19631966 NoElem ( bucket) => bucket. put ( self . hash , self . key , value) . into_mut_refs ( ) . 1 ,
19641967 }
19651968 }
0 commit comments