11use super :: either_iter:: EitherIter ;
22use crate :: fx:: FxHashMap ;
33use arrayvec:: ArrayVec ;
4- use std:: borrow:: Borrow ;
54use std:: fmt;
65use std:: hash:: Hash ;
76use std:: iter:: FromIterator ;
@@ -30,19 +29,45 @@ const SSO_ARRAY_SIZE: usize = 8;
3029///
3130/// Stores elements in a small array up to a certain length
3231/// and switches to `HashMap` when that length is exceeded.
33- ///
34- /// Implements subset of HashMap API.
35- ///
36- /// Missing HashMap API:
37- /// all hasher-related
38- /// try_reserve (unstable)
39- /// shrink_to (unstable)
40- /// drain_filter (unstable)
41- /// into_keys/into_values (unstable)
42- /// all raw_entry-related
43- /// PartialEq/Eq (requires sorting the array)
44- /// Entry::or_insert_with_key (unstable)
45- /// Vacant/Occupied entries and related
32+ //
33+ // FIXME: Implements subset of HashMap API.
34+ //
35+ // Missing HashMap API:
36+ // all hasher-related
37+ // try_reserve (unstable)
38+ // shrink_to (unstable)
39+ // drain_filter (unstable)
40+ // into_keys/into_values (unstable)
41+ // all raw_entry-related
42+ // PartialEq/Eq (requires sorting the array)
43+ // Entry::or_insert_with_key (unstable)
44+ // Vacant/Occupied entries and related
45+ //
46+ // FIXME: In HashMap most methods accepting key reference
47+ // accept reference to generic `Q` where `K: Borrow<Q>`.
48+ //
49+ // However, using this approach in `HashMap::get` apparently
50+ // breaks inlining and noticeably reduces performance.
51+ //
52+ // Performance *should* be the same given that borrow is
53+ // a NOP in most cases, but in practice that's not the case.
54+ //
55+ // Further investigation is required.
56+ //
57+ // Affected methods:
58+ // SsoHashMap::get
59+ // SsoHashMap::get_mut
60+ // SsoHashMap::get_entry
61+ // SsoHashMap::get_key_value
62+ // SsoHashMap::contains_key
63+ // SsoHashMap::remove
64+ // SsoHashMap::remove_entry
65+ // Index::index
66+ // SsoHashSet::take
67+ // SsoHashSet::get
68+ // SsoHashSet::remove
69+ // SsoHashSet::contains
70+
4671#[ derive( Clone ) ]
4772pub enum SsoHashMap < K , V > {
4873 Array ( ArrayVec < [ ( K , V ) ; SSO_ARRAY_SIZE ] > ) ,
@@ -232,14 +257,10 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
232257
233258 /// Removes a key from the map, returning the value at the key if the key
234259 /// was previously in the map.
235- pub fn remove < Q : ?Sized > ( & mut self , key : & Q ) -> Option < V >
236- where
237- K : Borrow < Q > ,
238- Q : Hash + Eq ,
239- {
260+ pub fn remove ( & mut self , key : & K ) -> Option < V > {
240261 match self {
241262 SsoHashMap :: Array ( array) => {
242- if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k. borrow ( ) == key) {
263+ if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k == key) {
243264 Some ( array. swap_remove ( index) . 1 )
244265 } else {
245266 None
@@ -251,14 +272,10 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
251272
252273 /// Removes a key from the map, returning the stored key and value if the
253274 /// key was previously in the map.
254- pub fn remove_entry < Q : ?Sized > ( & mut self , key : & Q ) -> Option < ( K , V ) >
255- where
256- K : Borrow < Q > ,
257- Q : Hash + Eq ,
258- {
275+ pub fn remove_entry ( & mut self , key : & K ) -> Option < ( K , V ) > {
259276 match self {
260277 SsoHashMap :: Array ( array) => {
261- if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k. borrow ( ) == key) {
278+ if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k == key) {
262279 Some ( array. swap_remove ( index) )
263280 } else {
264281 None
@@ -269,15 +286,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
269286 }
270287
271288 /// Returns a reference to the value corresponding to the key.
272- pub fn get < Q : ?Sized > ( & self , key : & Q ) -> Option < & V >
273- where
274- K : Borrow < Q > ,
275- Q : Hash + Eq ,
276- {
289+ pub fn get ( & self , key : & K ) -> Option < & V > {
277290 match self {
278291 SsoHashMap :: Array ( array) => {
279292 for ( k, v) in array {
280- if k. borrow ( ) == key {
293+ if k == key {
281294 return Some ( v) ;
282295 }
283296 }
@@ -288,15 +301,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
288301 }
289302
290303 /// Returns a mutable reference to the value corresponding to the key.
291- pub fn get_mut < Q : ?Sized > ( & mut self , key : & Q ) -> Option < & mut V >
292- where
293- K : Borrow < Q > ,
294- Q : Hash + Eq ,
295- {
304+ pub fn get_mut ( & mut self , key : & K ) -> Option < & mut V > {
296305 match self {
297306 SsoHashMap :: Array ( array) => {
298307 for ( k, v) in array {
299- if ( * k ) . borrow ( ) == key {
308+ if k == key {
300309 return Some ( v) ;
301310 }
302311 }
@@ -307,15 +316,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
307316 }
308317
309318 /// Returns the key-value pair corresponding to the supplied key.
310- pub fn get_key_value < Q : ?Sized > ( & self , key : & Q ) -> Option < ( & K , & V ) >
311- where
312- K : Borrow < Q > ,
313- Q : Hash + Eq ,
314- {
319+ pub fn get_key_value ( & self , key : & K ) -> Option < ( & K , & V ) > {
315320 match self {
316321 SsoHashMap :: Array ( array) => {
317322 for ( k, v) in array {
318- if k. borrow ( ) == key {
323+ if k == key {
319324 return Some ( ( k, v) ) ;
320325 }
321326 }
@@ -326,13 +331,9 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
326331 }
327332
328333 /// Returns `true` if the map contains a value for the specified key.
329- pub fn contains_key < Q : ?Sized > ( & self , key : & Q ) -> bool
330- where
331- K : Borrow < Q > ,
332- Q : Hash + Eq ,
333- {
334+ pub fn contains_key ( & self , key : & K ) -> bool {
334335 match self {
335- SsoHashMap :: Array ( array) => array. iter ( ) . any ( |( k, _v) | k. borrow ( ) == key) ,
336+ SsoHashMap :: Array ( array) => array. iter ( ) . any ( |( k, _v) | k == key) ,
336337 SsoHashMap :: Map ( map) => map. contains_key ( key) ,
337338 }
338339 }
@@ -483,15 +484,14 @@ where
483484 }
484485}
485486
486- impl < ' a , K , Q : ? Sized , V > Index < & ' a Q > for SsoHashMap < K , V >
487+ impl < ' a , K , V > Index < & ' a K > for SsoHashMap < K , V >
487488where
488- K : Eq + Hash + Borrow < Q > ,
489- Q : Eq + Hash ,
489+ K : Eq + Hash ,
490490{
491491 type Output = V ;
492492
493493 #[ inline]
494- fn index ( & self , key : & Q ) -> & V {
494+ fn index ( & self , key : & K ) -> & V {
495495 self . get ( key) . expect ( "no entry found for key" )
496496 }
497497}
0 commit comments