@@ -522,40 +522,44 @@ impl<K, V> IndexMapCore<K, V> {
522522 }
523523}
524524
525+ /// Reserve entries capacity, rounded up to match the indices (via `try_capacity`).
526+ fn reserve_entries < K , V > ( entries : & mut Entries < K , V > , additional : usize , try_capacity : usize ) {
527+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
528+ // requested more, do it and let them have the resulting panic.
529+ let try_capacity = try_capacity. min ( IndexMapCore :: < K , V > :: MAX_ENTRIES_CAPACITY ) ;
530+ let try_add = try_capacity - entries. len ( ) ;
531+ if try_add > additional && entries. try_reserve_exact ( try_add) . is_ok ( ) {
532+ return ;
533+ }
534+ entries. reserve_exact ( additional) ;
535+ }
536+
525537impl < ' a , K , V > RefMut < ' a , K , V > {
526538 #[ inline]
527539 fn new ( indices : & ' a mut Indices , entries : & ' a mut Entries < K , V > ) -> Self {
528540 Self { indices, entries }
529541 }
530542
531543 /// Reserve entries capacity, rounded up to match the indices
544+ #[ inline]
532545 fn reserve_entries ( & mut self , additional : usize ) {
533- // Use a soft-limit on the maximum capacity, but if the caller explicitly
534- // requested more, do it and let them have the resulting panic.
535- let new_capacity = Ord :: min (
536- self . indices . capacity ( ) ,
537- IndexMapCore :: < K , V > :: MAX_ENTRIES_CAPACITY ,
538- ) ;
539- let try_add = new_capacity - self . entries . len ( ) ;
540- if try_add > additional && self . entries . try_reserve_exact ( try_add) . is_ok ( ) {
541- return ;
542- }
543- self . entries . reserve_exact ( additional) ;
546+ reserve_entries ( self . entries , additional, self . indices . capacity ( ) ) ;
544547 }
545548
546549 /// Insert a key-value pair in `entries`,
547550 /// *without* checking whether it already exists.
548- fn insert_unique ( mut self , hash : HashValue , key : K , value : V ) -> OccupiedEntry < ' a , K , V > {
549- if self . entries . len ( ) == self . entries . capacity ( ) {
550- // Reserve our own capacity synced to the indices,
551- // rather than letting `Vec::push` just double it.
552- self . reserve_entries ( 1 ) ;
553- }
551+ fn insert_unique ( self , hash : HashValue , key : K , value : V ) -> OccupiedEntry < ' a , K , V > {
554552 let i = self . indices . len ( ) ;
553+ debug_assert_eq ! ( i, self . entries. len( ) ) ;
555554 let entry = self
556555 . indices
557556 . insert_unique ( hash. get ( ) , i, get_hash ( self . entries ) ) ;
558- debug_assert_eq ! ( i, self . entries. len( ) ) ;
557+ if self . entries . len ( ) == self . entries . capacity ( ) {
558+ // We can't call `indices.capacity()` while this `entry` has borrowed it, so we'll have
559+ // to amortize growth on our own. It's still an improvement over the basic `Vec::push`
560+ // doubling though, since we also consider `MAX_ENTRIES_CAPACITY`.
561+ reserve_entries ( self . entries , 1 , 2 * self . entries . capacity ( ) ) ;
562+ }
559563 self . entries . push ( Bucket { hash, key, value } ) ;
560564 OccupiedEntry :: new ( self . entries , entry)
561565 }
0 commit comments