about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2021-10-21 14:11:13 +0900
committerGitHub <noreply@github.com>2021-10-21 14:11:13 +0900
commit3680ecd8a6e8dcac98833bc8bbc349277f780419 (patch)
treec96cd17109ce7c0f9bd8ea0e2d5ab1e4f6cf56ef
parent68a5680fc5961f1c91e79debae2f0994c1136a69 (diff)
parent0aa68a8db9dfffb2756279cc621b1b15a896423d (diff)
downloadrust-3680ecd8a6e8dcac98833bc8bbc349277f780419.tar.gz
rust-3680ecd8a6e8dcac98833bc8bbc349277f780419.zip
Rollup merge of #90099 - SkiFire13:fix-vec-swap-remove, r=dtolnay
Fix MIRI UB in `Vec::swap_remove`

Fixes #90055

I find it weird that `Vec::swap_remove` read the last element to the stack just to immediately put it back in the `Vec` in place of the one at index `index`. It seems much more natural to me to just read the element at position `index` and then move the last element in its place. I guess this might also slightly improve codegen.
-rw-r--r--library/alloc/src/vec/mod.rs7
1 files changed, 4 insertions, 3 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 20a16869cb3..d52c78eedf3 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1305,10 +1305,11 @@ impl<T, A: Allocator> Vec<T, A> {
             // We replace self[index] with the last element. Note that if the
             // bounds check above succeeds there must be a last element (which
             // can be self[index] itself).
-            let last = ptr::read(self.as_ptr().add(len - 1));
-            let hole = self.as_mut_ptr().add(index);
+            let value = ptr::read(self.as_ptr().add(index));
+            let base_ptr = self.as_mut_ptr();
+            ptr::copy(base_ptr.add(len - 1), base_ptr.add(index), 1);
             self.set_len(len - 1);
-            ptr::replace(hole, last)
+            value
         }
     }