diff options
| author | bors <bors@rust-lang.org> | 2018-07-09 04:42:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-07-09 04:42:27 +0000 |
| commit | a80a610a4c30b6f5f60862afcb4588d03439f66c (patch) | |
| tree | bf310e3e568f661dc20086c8b216b0403252cdb5 /src/liballoc | |
| parent | 960f6046c6d367a48f405dd5c76cc303497edfc5 (diff) | |
| parent | e529dfd590e6c7e0c19bbf0f3c72e34f25c0cfb8 (diff) | |
| download | rust-a80a610a4c30b6f5f60862afcb4588d03439f66c.tar.gz rust-a80a610a4c30b6f5f60862afcb4588d03439f66c.zip | |
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 https://github.com/rust-lang/rust/issues/52150.
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/vec.rs | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index fbbaced540e..5efe1e23309 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -809,9 +809,15 @@ impl<T> Vec<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn swap_remove(&mut self, index: usize) -> T { - let length = self.len(); - self.swap(index, length - 1); - self.pop().unwrap() + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check on hole succeeds there must be a last element (which + // can be self[index] itself). + let hole: *mut T = &mut self[index]; + let last = ptr::read(self.get_unchecked(self.len - 1)); + self.len -= 1; + ptr::replace(hole, last) + } } /// Inserts an element at position `index` within the vector, shifting all |
