@@ -21,7 +21,7 @@ use fmt::{self, Debug};
21
21
use hash:: { Hash , SipHasher } ;
22
22
use iter:: { Iterator , ExactSizeIterator , IntoIterator , IteratorExt , FromIterator , Extend , Map } ;
23
23
use marker:: Sized ;
24
- use mem:: { self , replace} ;
24
+ use mem:: { self , swap , replace} ;
25
25
use num:: { Int , UnsignedInt } ;
26
26
use ops:: { Deref , DerefMut , Drop , FnMut , Index , IndexMut } ;
27
27
use option:: Option :: { self , Some , None } ;
@@ -393,8 +393,8 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
393
393
fn robin_hood < ' a , K : ' a , V : ' a > ( bucket : FullBucketMut < ' a , K , V > ,
394
394
mut ib : usize ,
395
395
mut hash : SafeHash ,
396
- mut k : K ,
397
- mut v : V )
396
+ mut key : K ,
397
+ mut val : V )
398
398
-> & ' a mut V {
399
399
let starting_index = bucket. index ( ) ;
400
400
let size = {
@@ -408,9 +408,11 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
408
408
let idx_end = starting_index + size - bucket. displacement ( ) ;
409
409
410
410
loop {
411
- let ( old_hash , old_key , old_val ) = {
411
+ {
412
412
let ( h_ref, k_ref, v_ref) = bucket. read_mut ( ) ;
413
- ( replace ( h_ref, hash) , replace ( k_ref, k) , replace ( v_ref, v) )
413
+ swap ( h_ref, & mut hash) ;
414
+ swap ( k_ref, & mut key) ;
415
+ swap ( v_ref, & mut val) ) ;
414
416
} ;
415
417
loop {
416
418
let probe = bucket. into_next ( ) ;
@@ -419,7 +421,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
419
421
let full_bucket = match probe. peek ( ) {
420
422
Empty ( bucket) => {
421
423
// Found a hole!
422
- let b = bucket. put ( old_hash , old_key , old_val ) ;
424
+ let b = bucket. put ( hash , key , val ) ;
423
425
// Now that it's stolen, just read the value's pointer
424
426
// right out of the table!
425
427
return b. into_table ( ) . into_mut_refs ( ) . 1 ;
@@ -434,9 +436,6 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
434
436
// Robin hood! Steal the spot.
435
437
if ib < probe_ib {
436
438
ib = probe_ib;
437
- hash = old_hash;
438
- k = old_key;
439
- v = old_val;
440
439
break ;
441
440
}
442
441
}
@@ -478,24 +477,20 @@ impl<K, V, S> HashMap<K, V, S>
478
477
/// Search for a key, yielding the index if it's found in the hashtable.
479
478
/// If you already have the hash for the key lying around, use
480
479
/// search_hashed.
481
- fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q ) -> Option < FullBucketImm < ' a , K , V > >
480
+ fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q )
481
+ -> Option < InternalEntry < K , V , & ' a RawTable < K , V > > >
482
482
where K : Borrow < Q > , Q : Eq + Hash
483
483
{
484
484
let hash = self . make_hash ( q) ;
485
- match search_hashed ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) ) {
486
- InternalEntry :: Occupied ( bucket) => Some ( bucket. elem ) ,
487
- _ => None ,
488
- }
485
+ search_hashed ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
489
486
}
490
487
491
- fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q ) -> Option < FullBucketMut < ' a , K , V > >
488
+ fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q )
489
+ -> Option < InternalEntry < K , V , & ' a mut RawTable < K , V > > >
492
490
where K : Borrow < Q > , Q : Eq + Hash
493
491
{
494
492
let hash = self . make_hash ( q) ;
495
- match search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) ) {
496
- InternalEntry :: Occupied ( bucket) => Some ( bucket. elem ) ,
497
- _ => None ,
498
- }
493
+ search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
499
494
}
500
495
}
501
496
@@ -773,7 +768,15 @@ impl<K, V, S> HashMap<K, V, S>
773
768
774
769
// Shrink the table. Naive algorithm for resizing:
775
770
while let Some ( ( h, k, v) ) = old_table. take_front ( ) {
776
- self . insert_hashed_nocheck ( h, k, v) ;
771
+ match search_hashed ( & mut self . table , hash, |key| * key == k) {
772
+ InternalEntry :: Vacant ( entry) => {
773
+ entry. insert ( hash, k, v) ;
774
+ }
775
+ InternalEntry :: Occupied ( mut entry) => {
776
+ entry. insert ( v) ;
777
+ }
778
+ InternalEntry :: TableIsEmpty => unreachable ! ( )
779
+ }
777
780
}
778
781
779
782
debug_assert_eq ! ( self . table. size( ) , old_size) ;
@@ -935,8 +938,7 @@ impl<K, V, S> HashMap<K, V, S>
935
938
// Gotta resize now.
936
939
self . reserve ( 1 ) ;
937
940
938
- let hash = self . make_hash ( & key) ;
939
- match search_hashed ( & mut self . table , hash, |k| * k == key) {
941
+ match self . search_mut ( & key) {
940
942
InternalEntry :: Occupied ( state) => Occupied ( state) ,
941
943
InternalEntry :: Vacant ( bucket) => Vacant ( VacantEntry {
942
944
elem : bucket,
@@ -1045,7 +1047,7 @@ impl<K, V, S> HashMap<K, V, S>
1045
1047
pub fn get < Q : ?Sized > ( & self , k : & Q ) -> Option < & V >
1046
1048
where K : Borrow < Q > , Q : Hash + Eq
1047
1049
{
1048
- self . search ( k) . map ( |bucket| bucket. into_refs ( ) . 1 )
1050
+ self . search ( k) . into_option ( ) . map ( |bucket| bucket. into_refs ( ) . 1 )
1049
1051
}
1050
1052
1051
1053
/// Returns true if the map contains a value for the specified key.
@@ -1068,7 +1070,7 @@ impl<K, V, S> HashMap<K, V, S>
1068
1070
pub fn contains_key < Q : ?Sized > ( & self , k : & Q ) -> bool
1069
1071
where K : Borrow < Q > , Q : Hash + Eq
1070
1072
{
1071
- self . search ( k) . is_some ( )
1073
+ self . search ( k) . into_option ( ) . is_some ( )
1072
1074
}
1073
1075
1074
1076
/// Returns a mutable reference to the value corresponding to the key.
@@ -1094,7 +1096,7 @@ impl<K, V, S> HashMap<K, V, S>
1094
1096
pub fn get_mut < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V >
1095
1097
where K : Borrow < Q > , Q : Hash + Eq
1096
1098
{
1097
- self . search_mut ( k) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
1099
+ self . search_mut ( k) . into_option ( ) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
1098
1100
}
1099
1101
1100
1102
/// Inserts a key-value pair from the map. If the key already had a value
@@ -1114,10 +1116,19 @@ impl<K, V, S> HashMap<K, V, S>
1114
1116
/// assert_eq!(map[37], "c");
1115
1117
/// ```
1116
1118
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1117
- pub fn insert ( & mut self , k : K , v : V ) -> Option < V > {
1118
- let hash = self . make_hash ( & k) ;
1119
+ pub fn insert ( & mut self , key : K , value : V ) -> Option < V > {
1119
1120
self . reserve ( 1 ) ;
1120
- self . insert_hashed_nocheck ( hash, k, v)
1121
+
1122
+ match self . search_mut ( & key) {
1123
+ InternalEntry :: Vacant ( entry) => {
1124
+ entry. insert ( hash, key, value) ;
1125
+ return None ;
1126
+ }
1127
+ InternalEntry :: Occupied ( mut entry) => {
1128
+ return Some ( entry. insert ( value) ) ;
1129
+ }
1130
+ InternalEntry :: TableIsEmpty => unreachable ! ( )
1131
+ }
1121
1132
}
1122
1133
1123
1134
/// Removes a key from the map, returning the value at the key if the key
@@ -1145,7 +1156,7 @@ impl<K, V, S> HashMap<K, V, S>
1145
1156
return None
1146
1157
}
1147
1158
1148
- self . search_mut ( k) . map ( |bucket| pop_internal ( bucket) . 1 )
1159
+ self . search_mut ( k) . into_option ( ) . map ( |bucket| pop_internal ( bucket) . 1 )
1149
1160
}
1150
1161
}
1151
1162
@@ -1398,6 +1409,15 @@ enum InternalEntry<K, V, M> {
1398
1409
TableIsEmpty ,
1399
1410
}
1400
1411
1412
+ impl < K , V , M > InternalEntry < K , V , M > {
1413
+ fn into_option ( self ) -> Option < FullBucket < K , V , M > > {
1414
+ match self {
1415
+ InternalEntry :: Occupied ( bucket) => Some ( bucket. elem ) ,
1416
+ _ => None ,
1417
+ }
1418
+ }
1419
+ }
1420
+
1401
1421
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1402
1422
impl < ' a , K , V > Iterator for Iter < ' a , K , V > {
1403
1423
type Item = ( & ' a K , & ' a V ) ;
0 commit comments