@@ -398,8 +398,9 @@ pub struct HashMap<K, V, S = RandomState> {
398398}
399399
400400/// Search for a pre-hashed key.
401+ /// If you don't already know the hash, use search or search_mut instead
401402#[ inline]
402- fn search_hashed < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F ) -> InternalEntry < K , V , M >
403+ fn search_hashed < K , V , M , F > ( table : M , hash : SafeHash , is_match : F ) -> InternalEntry < K , V , M >
403404 where M : Deref < Target = RawTable < K , V > > ,
404405 F : FnMut ( & K ) -> bool
405406{
@@ -410,6 +411,18 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
410411 return InternalEntry :: TableIsEmpty ;
411412 }
412413
414+ search_hashed_nonempty ( table, hash, is_match)
415+ }
416+
417+ /// Search for a pre-hashed key when the hash map is known to be non-empty.
418+ #[ inline]
419+ fn search_hashed_nonempty < K , V , M , F > ( table : M , hash : SafeHash , mut is_match : F )
420+ -> InternalEntry < K , V , M >
421+ where M : Deref < Target = RawTable < K , V > > ,
422+ F : FnMut ( & K ) -> bool
423+ {
424+ // Do not check the capacity as an extra branch could slow the lookup.
425+
413426 let size = table. size ( ) ;
414427 let mut probe = Bucket :: new ( table, hash) ;
415428 let mut displacement = 0 ;
@@ -543,24 +556,36 @@ impl<K, V, S> HashMap<K, V, S>
543556 }
544557
545558 /// Search for a key, yielding the index if it's found in the hashtable.
546- /// If you already have the hash for the key lying around, use
547- /// search_hashed.
559+ /// If you already have the hash for the key lying around, or if you need an
560+ /// InternalEntry, use search_hashed or search_hashed_nonempty .
548561 #[ inline]
549- fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q ) -> InternalEntry < K , V , & ' a RawTable < K , V > >
562+ fn search < ' a , Q : ?Sized > ( & ' a self , q : & Q )
563+ -> Option < FullBucket < K , V , & ' a RawTable < K , V > > >
550564 where K : Borrow < Q > ,
551565 Q : Eq + Hash
552566 {
567+ if self . is_empty ( ) {
568+ return None ;
569+ }
570+
553571 let hash = self . make_hash ( q) ;
554- search_hashed ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
572+ search_hashed_nonempty ( & self . table , hash, |k| q. eq ( k. borrow ( ) ) )
573+ . into_occupied_bucket ( )
555574 }
556575
557576 #[ inline]
558- fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q ) -> InternalEntry < K , V , & ' a mut RawTable < K , V > >
577+ fn search_mut < ' a , Q : ?Sized > ( & ' a mut self , q : & Q )
578+ -> Option < FullBucket < K , V , & ' a mut RawTable < K , V > > >
559579 where K : Borrow < Q > ,
560580 Q : Eq + Hash
561581 {
582+ if self . is_empty ( ) {
583+ return None ;
584+ }
585+
562586 let hash = self . make_hash ( q) ;
563- search_hashed ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
587+ search_hashed_nonempty ( & mut self . table , hash, |k| q. eq ( k. borrow ( ) ) )
588+ . into_occupied_bucket ( )
564589 }
565590
566591 // The caller should ensure that invariants by Robin Hood Hashing hold
@@ -1118,7 +1143,7 @@ impl<K, V, S> HashMap<K, V, S>
11181143 where K : Borrow < Q > ,
11191144 Q : Hash + Eq
11201145 {
1121- self . search ( k) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_refs ( ) . 1 )
1146+ self . search ( k) . map ( |bucket| bucket. into_refs ( ) . 1 )
11221147 }
11231148
11241149 /// Returns true if the map contains a value for the specified key.
@@ -1145,7 +1170,7 @@ impl<K, V, S> HashMap<K, V, S>
11451170 where K : Borrow < Q > ,
11461171 Q : Hash + Eq
11471172 {
1148- self . search ( k) . into_occupied_bucket ( ) . is_some ( )
1173+ self . search ( k) . is_some ( )
11491174 }
11501175
11511176 /// Returns a mutable reference to the value corresponding to the key.
@@ -1174,7 +1199,7 @@ impl<K, V, S> HashMap<K, V, S>
11741199 where K : Borrow < Q > ,
11751200 Q : Hash + Eq
11761201 {
1177- self . search_mut ( k) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
1202+ self . search_mut ( k) . map ( |bucket| bucket. into_mut_refs ( ) . 1 )
11781203 }
11791204
11801205 /// Inserts a key-value pair into the map.
@@ -1234,11 +1259,7 @@ impl<K, V, S> HashMap<K, V, S>
12341259 where K : Borrow < Q > ,
12351260 Q : Hash + Eq
12361261 {
1237- if self . table . size ( ) == 0 {
1238- return None ;
1239- }
1240-
1241- self . search_mut ( k) . into_occupied_bucket ( ) . map ( |bucket| pop_internal ( bucket) . 1 )
1262+ self . search_mut ( k) . map ( |bucket| pop_internal ( bucket) . 1 )
12421263 }
12431264
12441265 /// Removes a key from the map, returning the stored key and value if the
@@ -1269,12 +1290,7 @@ impl<K, V, S> HashMap<K, V, S>
12691290 where K : Borrow < Q > ,
12701291 Q : Hash + Eq
12711292 {
1272- if self . table . size ( ) == 0 {
1273- return None ;
1274- }
1275-
12761293 self . search_mut ( k)
1277- . into_occupied_bucket ( )
12781294 . map ( |bucket| {
12791295 let ( k, v, _) = pop_internal ( bucket) ;
12801296 ( k, v)
@@ -2632,15 +2648,11 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
26322648
26332649 #[ inline]
26342650 fn get ( & self , key : & Q ) -> Option < & K > {
2635- self . search ( key) . into_occupied_bucket ( ) . map ( |bucket| bucket. into_refs ( ) . 0 )
2651+ self . search ( key) . map ( |bucket| bucket. into_refs ( ) . 0 )
26362652 }
26372653
26382654 fn take ( & mut self , key : & Q ) -> Option < K > {
2639- if self . table . size ( ) == 0 {
2640- return None ;
2641- }
2642-
2643- self . search_mut ( key) . into_occupied_bucket ( ) . map ( |bucket| pop_internal ( bucket) . 0 )
2655+ self . search_mut ( key) . map ( |bucket| pop_internal ( bucket) . 0 )
26442656 }
26452657
26462658 #[ inline]
0 commit comments