Skip to content

Commit a80a610

Browse files
committed
Auto merge of #52166 - orlp:master, r=joshtriplett
Performance improvement of Vec's swap_remove. The old implementation *literally* swapped and then removed, which resulted in unnecessary move instructions. The new implementation does use unsafe code, but is easy to see that it is correct. Fixes #52150.
2 parents 960f604 + e529dfd commit a80a610

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/liballoc/vec.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -809,9 +809,15 @@ impl<T> Vec<T> {
809809
#[inline]
810810
#[stable(feature = "rust1", since = "1.0.0")]
811811
pub fn swap_remove(&mut self, index: usize) -> T {
812-
let length = self.len();
813-
self.swap(index, length - 1);
814-
self.pop().unwrap()
812+
unsafe {
813+
// We replace self[index] with the last element. Note that if the
814+
// bounds check on hole succeeds there must be a last element (which
815+
// can be self[index] itself).
816+
let hole: *mut T = &mut self[index];
817+
let last = ptr::read(self.get_unchecked(self.len - 1));
818+
self.len -= 1;
819+
ptr::replace(hole, last)
820+
}
815821
}
816822

817823
/// Inserts an element at position `index` within the vector, shifting all

0 commit comments

Comments
 (0)