@@ -216,6 +216,8 @@ impl<K, V> IndexMapCore<K, V> {
216216 K : Eq ,
217217 {
218218 match self . find_equivalent ( hash, & key) {
219+ // Safety: The entry is created with a live raw bucket, at the same time we have a &mut
220+ // reference to the map, so it can not be modified further.
219221 Some ( raw_bucket) => Entry :: Occupied ( OccupiedEntry {
220222 map : self ,
221223 raw_bucket,
@@ -250,7 +252,7 @@ impl<K, V> IndexMapCore<K, V> {
250252 Q : ?Sized + Equivalent < K > ,
251253 {
252254 match self . find_equivalent ( hash, key) {
253- Some ( raw_bucket) => Some ( self . shift_remove_bucket ( raw_bucket) ) ,
255+ Some ( raw_bucket) => unsafe { Some ( self . shift_remove_bucket ( raw_bucket) ) } ,
254256 None => None ,
255257 }
256258 }
@@ -261,12 +263,17 @@ impl<K, V> IndexMapCore<K, V> {
261263 Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
262264 None => return None ,
263265 } ;
264- let ( _, key, value) = self . shift_remove_bucket ( raw_bucket) ;
265- Some ( ( key, value) )
266+ unsafe {
267+ let ( _, key, value) = self . shift_remove_bucket ( raw_bucket) ;
268+ Some ( ( key, value) )
269+ }
266270 }
267271
268272 /// Remove an entry by shifting all entries that follow it
269- fn shift_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
273+ ///
274+ /// Safety: The caller must pass a live `raw_bucket`.
275+ #[ allow( unused_unsafe) ]
276+ unsafe fn shift_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
270277 // use Vec::remove, but then we need to update the indices that point
271278 // to all of the other entries that have to move
272279 let index = unsafe {
@@ -306,7 +313,7 @@ impl<K, V> IndexMapCore<K, V> {
306313 Q : ?Sized + Equivalent < K > ,
307314 {
308315 match self . find_equivalent ( hash, key) {
309- Some ( raw_bucket) => Some ( self . swap_remove_bucket ( raw_bucket) ) ,
316+ Some ( raw_bucket) => unsafe { Some ( self . swap_remove_bucket ( raw_bucket) ) } ,
310317 None => None ,
311318 }
312319 }
@@ -317,12 +324,17 @@ impl<K, V> IndexMapCore<K, V> {
317324 Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
318325 None => return None ,
319326 } ;
320- let ( _, key, value) = self . swap_remove_bucket ( raw_bucket) ;
321- Some ( ( key, value) )
327+ unsafe {
328+ let ( _, key, value) = self . swap_remove_bucket ( raw_bucket) ;
329+ Some ( ( key, value) )
330+ }
322331 }
323332
324333 /// Remove an entry by swapping it with the last
325- fn swap_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
334+ ///
335+ /// Safety: The caller must pass a live `raw_bucket`.
336+ #[ allow( unused_unsafe) ]
337+ unsafe fn swap_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
326338 // use swap_remove, but then we need to update the index that points
327339 // to the other entry that has to move
328340 let index = unsafe {
@@ -570,8 +582,12 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
570582 ///
571583 /// Computes in **O(1)** time (average).
572584 pub fn swap_remove_entry ( self ) -> ( K , V ) {
573- let ( _, key, value) = self . map . swap_remove_bucket ( self . raw_bucket ) ;
574- ( key, value)
585+ // This is safe because it can only happen once (self is consumed)
586+ // and map.indices have not been modified since entry construction
587+ unsafe {
588+ let ( _, key, value) = self . map . swap_remove_bucket ( self . raw_bucket ) ;
589+ ( key, value)
590+ }
575591 }
576592
577593 /// Remove and return the key, value pair stored in the map for this entry
@@ -582,8 +598,12 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
582598 ///
583599 /// Computes in **O(n)** time (average).
584600 pub fn shift_remove_entry ( self ) -> ( K , V ) {
585- let ( _, key, value) = self . map . shift_remove_bucket ( self . raw_bucket ) ;
586- ( key, value)
601+ // This is safe because it can only happen once (self is consumed)
602+ // and map.indices have not been modified since entry construction
603+ unsafe {
604+ let ( _, key, value) = self . map . shift_remove_bucket ( self . raw_bucket ) ;
605+ ( key, value)
606+ }
587607 }
588608}
589609
0 commit comments