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