about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-09-14 16:42:28 +0200
committerGitHub <noreply@github.com>2019-09-14 16:42:28 +0200
commitc6c2acdb47d320658d22b0ac0f8a357fdc071b1f (patch)
tree001224f37a46a755ced70fb8f9ea9e85fba29d8d /src/liballoc
parentaf33a1d902c7dec7824740e971953b21996d4429 (diff)
parent223600ac2c23715f350ceae7f315f5056aae6fc0 (diff)
downloadrust-c6c2acdb47d320658d22b0ac0f8a357fdc071b1f.tar.gz
rust-c6c2acdb47d320658d22b0ac0f8a357fdc071b1f.zip
Rollup merge of #64375 - kornelski:vecdrop, r=rkruppe
Fast path for vec.clear/truncate

For trivial types like `u8`, `vec.truncate()`/`vec.clear()` relies on the optimizer to remove the loop. This means more work in debug builds, and more work for the optimizer.

Avoiding this busywork is exactly what `mem::needs_drop::<T>()` is for.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/vec.rs30
1 files changed, 17 insertions, 13 deletions
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index d5dc2d4b868..c513658c842 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -685,21 +685,25 @@ impl<T> Vec<T> {
     /// [`drain`]: #method.drain
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
-        let current_len = self.len;
-        unsafe {
-            let mut ptr = self.as_mut_ptr().add(self.len);
-            // Set the final length at the end, keeping in mind that
-            // dropping an element might panic. Works around a missed
-            // optimization, as seen in the following issue:
-            // https://github.com/rust-lang/rust/issues/51802
-            let mut local_len = SetLenOnDrop::new(&mut self.len);
+        if mem::needs_drop::<T>() {
+            let current_len = self.len;
+            unsafe {
+                let mut ptr = self.as_mut_ptr().add(self.len);
+                // Set the final length at the end, keeping in mind that
+                // dropping an element might panic. Works around a missed
+                // optimization, as seen in the following issue:
+                // https://github.com/rust-lang/rust/issues/51802
+                let mut local_len = SetLenOnDrop::new(&mut self.len);
 
-            // drop any extra elements
-            for _ in len..current_len {
-                local_len.decrement_len(1);
-                ptr = ptr.offset(-1);
-                ptr::drop_in_place(ptr);
+                // drop any extra elements
+                for _ in len..current_len {
+                    local_len.decrement_len(1);
+                    ptr = ptr.offset(-1);
+                    ptr::drop_in_place(ptr);
+                }
             }
+        } else if len <= self.len {
+            self.len = len;
         }
     }