]> git.lizzy.rs Git - rust.git/commitdiff
fix and test aliasing in swap_remove
authorRalf Jung <post@ralfj.de>
Mon, 30 Mar 2020 11:31:16 +0000 (13:31 +0200)
committerRalf Jung <post@ralfj.de>
Mon, 30 Mar 2020 11:34:03 +0000 (13:34 +0200)
src/liballoc/tests/vec.rs
src/liballoc/vec.rs

index a90bc58cbfd5d10ba1f8cce6edcf48953753c6a6..6321e7154e7d091e7617a6007e79522185f84876 100644 (file)
@@ -1378,6 +1378,11 @@ fn next_then_drop<I: Iterator>(mut i: I) {
     v.remove(1);
     v.pop().unwrap();
     assert_eq!(*v0, 13);
+    v.push(1);
+    v.swap_remove(1);
+    assert_eq!(v.len(), 2);
+    v.swap_remove(1); // swap_remove the last element
+    assert_eq!(*v0, 13);
 
     // Appending
     v.append(&mut vec![27, 19]);
index dc2a246f817761d54521fc41d11ae62b5f440939..c600a6b649f36fdfba5688f9f0bc8cccc540e7f4 100644 (file)
@@ -963,12 +963,13 @@ pub unsafe fn set_len(&mut self, new_len: usize) {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap_remove(&mut self, index: usize) -> T {
+        assert!(index < self.len);
         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
+            // bounds check above 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));
+            let last = ptr::read(self.as_ptr().add(self.len - 1));
+            let hole: *mut T = self.as_mut_ptr().add(index);
             self.len -= 1;
             ptr::replace(hole, last)
         }