@@ -216,6 +216,8 @@ impl<K, V> IndexMapCore<K, V> {
216
216
K : Eq ,
217
217
{
218
218
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.
219
221
Some ( raw_bucket) => Entry :: Occupied ( OccupiedEntry {
220
222
map : self ,
221
223
raw_bucket,
@@ -250,7 +252,7 @@ impl<K, V> IndexMapCore<K, V> {
250
252
Q : ?Sized + Equivalent < K > ,
251
253
{
252
254
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) ) } ,
254
256
None => None ,
255
257
}
256
258
}
@@ -261,12 +263,17 @@ impl<K, V> IndexMapCore<K, V> {
261
263
Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
262
264
None => return None ,
263
265
} ;
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
+ }
266
270
}
267
271
268
272
/// 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 ) {
270
277
// use Vec::remove, but then we need to update the indices that point
271
278
// to all of the other entries that have to move
272
279
let index = unsafe {
@@ -306,7 +313,7 @@ impl<K, V> IndexMapCore<K, V> {
306
313
Q : ?Sized + Equivalent < K > ,
307
314
{
308
315
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) ) } ,
310
317
None => None ,
311
318
}
312
319
}
@@ -317,12 +324,17 @@ impl<K, V> IndexMapCore<K, V> {
317
324
Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
318
325
None => return None ,
319
326
} ;
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
+ }
322
331
}
323
332
324
333
/// 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 ) {
326
338
// use swap_remove, but then we need to update the index that points
327
339
// to the other entry that has to move
328
340
let index = unsafe {
@@ -570,8 +582,12 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
570
582
///
571
583
/// Computes in **O(1)** time (average).
572
584
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
+ }
575
591
}
576
592
577
593
/// 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> {
582
598
///
583
599
/// Computes in **O(n)** time (average).
584
600
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
+ }
587
607
}
588
608
}
589
609
0 commit comments