@@ -21,7 +21,7 @@ use fmt::{self, Debug};
2121use hash:: { Hash , SipHasher } ;
2222use iter:: { Iterator , ExactSizeIterator , IntoIterator , IteratorExt , FromIterator , Extend , Map } ;
2323use marker:: Sized ;
24- use mem:: { self , replace} ;
24+ use mem:: { self , swap , replace} ;
2525use num:: { Int , UnsignedInt } ;
2626use ops:: { Deref , DerefMut , Drop , FnMut , Index , IndexMut } ;
2727use option:: Option :: { self , Some , None } ;
@@ -393,8 +393,8 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
393393fn robin_hood < ' a , K : ' a , V : ' a > ( bucket : FullBucketMut < ' a , K , V > ,
394394 mut ib : usize ,
395395 mut hash : SafeHash ,
396- mut k : K ,
397- mut v : V )
396+ mut key : K ,
397+ mut val : V )
398398 -> & ' a mut V {
399399 let starting_index = bucket. index ( ) ;
400400 let size = {
@@ -408,9 +408,11 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
408408 let idx_end = starting_index + size - bucket. displacement ( ) ;
409409
410410 loop {
411- let ( old_hash , old_key , old_val ) = {
411+ {
412412 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) ) ;
414416 } ;
415417 loop {
416418 let probe = bucket. into_next ( ) ;
@@ -419,7 +421,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
419421 let full_bucket = match probe. peek ( ) {
420422 Empty ( bucket) => {
421423 // Found a hole!
422- let b = bucket. put ( old_hash , old_key , old_val ) ;
424+ let b = bucket. put ( hash , key , val ) ;
423425 // Now that it's stolen, just read the value's pointer
424426 // right out of the table!
425427 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>,
434436 // Robin hood! Steal the spot.
435437 if ib < probe_ib {
436438 ib = probe_ib;
437- hash = old_hash;
438- k = old_key;
439- v = old_val;
440439 break ;
441440 }
442441 }
@@ -478,24 +477,20 @@ impl<K, V, S> HashMap<K, V, S>
478477 /// Search for a key, yielding the index if it's found in the hashtable.
479478 /// If you already have the hash for the key lying around, use
480479 /// 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 > > >
482482 where K : Borrow < Q > , Q : Eq + Hash
483483 {
484484 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 ( ) ) )
489486 }
490487
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 > > >
492490 where K : Borrow < Q > , Q : Eq + Hash
493491 {
494492 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 ( ) ) )
499494 }
500495}
501496
@@ -773,7 +768,15 @@ impl<K, V, S> HashMap<K, V, S>
773768
774769 // Shrink the table. Naive algorithm for resizing:
775770 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+ }
777780 }
778781
779782 debug_assert_eq ! ( self . table. size( ) , old_size) ;
@@ -935,8 +938,7 @@ impl<K, V, S> HashMap<K, V, S>
935938 // Gotta resize now.
936939 self . reserve ( 1 ) ;
937940
938- let hash = self . make_hash ( & key) ;
939- match search_hashed ( & mut self . table , hash, |k| * k == key) {
941+ match self . search_mut ( & key) {
940942 InternalEntry :: Occupied ( state) => Occupied ( state) ,
941943 InternalEntry :: Vacant ( bucket) => Vacant ( VacantEntry {
942944 elem : bucket,
@@ -1045,7 +1047,7 @@ impl<K, V, S> HashMap<K, V, S>
10451047 pub fn get < Q : ?Sized > ( & self , k : & Q ) -> Option < & V >
10461048 where K : Borrow < Q > , Q : Hash + Eq
10471049 {
1048- self . search ( k) . map ( |bucket| bucket. into_refs ( ) . 1 )
1050+ self . search ( k) . into_option ( ) . map ( |bucket| bucket. into_refs ( ) . 1 )
10491051 }
10501052
10511053 /// Returns true if the map contains a value for the specified key.
@@ -1068,7 +1070,7 @@ impl<K, V, S> HashMap<K, V, S>
10681070 pub fn contains_key < Q : ?Sized > ( & self , k : & Q ) -> bool
10691071 where K : Borrow < Q > , Q : Hash + Eq
10701072 {
1071- self . search ( k) . is_some ( )
1073+ self . search ( k) . into_option ( ) . is_some ( )
10721074 }
10731075
10741076 /// Returns a mutable reference to the value corresponding to the key.
@@ -1094,7 +1096,7 @@ impl<K, V, S> HashMap<K, V, S>
10941096 pub fn get_mut < Q : ?Sized > ( & mut self , k : & Q ) -> Option < & mut V >
10951097 where K : Borrow < Q > , Q : Hash + Eq
10961098 {
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 )
10981100 }
10991101
11001102 /// 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>
11141116 /// assert_eq!(map[37], "c");
11151117 /// ```
11161118 #[ 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 > {
11191120 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+ }
11211132 }
11221133
11231134 /// 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>
11451156 return None
11461157 }
11471158
1148- self . search_mut ( k) . map ( |bucket| pop_internal ( bucket) . 1 )
1159+ self . search_mut ( k) . into_option ( ) . map ( |bucket| pop_internal ( bucket) . 1 )
11491160 }
11501161}
11511162
@@ -1398,6 +1409,15 @@ enum InternalEntry<K, V, M> {
13981409 TableIsEmpty ,
13991410}
14001411
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+
14011421#[ stable( feature = "rust1" , since = "1.0.0" ) ]
14021422impl < ' a , K , V > Iterator for Iter < ' a , K , V > {
14031423 type Item = ( & ' a K , & ' a V ) ;
0 commit comments