about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2020-01-26 20:50:05 +0100
committerThe8472 <git@infinite-source.de>2020-09-03 20:59:29 +0200
commit771b8ecc83ed55de617cdb29e05d509cfc745a8a (patch)
tree15153cb4142aca0a859fc1db5cf263cc564dab51
parent6ad133443a7975b2e86a3bbba16da33c769eeabc (diff)
downloadrust-771b8ecc83ed55de617cdb29e05d509cfc745a8a.tar.gz
rust-771b8ecc83ed55de617cdb29e05d509cfc745a8a.zip
extract IntoIter drop/forget used by specialization into separate methods
-rw-r--r--library/alloc/src/vec.rs40
1 files changed, 25 insertions, 15 deletions
diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs
index e799a4ce852..97dd04fbe70 100644
--- a/library/alloc/src/vec.rs
+++ b/library/alloc/src/vec.rs
@@ -2226,9 +2226,9 @@ where
             return SpecFromNested::from_iter(iterator);
         }
 
-        let (src_buf, src_end) = {
+        let (src_buf, src_end, cap) = {
             let inner = unsafe { iterator.as_inner().as_into_iter() };
-            (inner.buf.as_ptr(), inner.end)
+            (inner.buf.as_ptr(), inner.end, inner.cap)
         };
         let dst = src_buf;
 
@@ -2278,23 +2278,15 @@ where
         debug_assert_eq!(src_buf, src.buf.as_ptr());
         debug_assert!(dst as *const _ <= src.ptr, "InPlaceIterable contract violation");
 
-        if mem::needs_drop::<T>() {
-            // drop tail if iterator was only partially exhausted
-            unsafe {
-                ptr::drop_in_place(src.as_mut_slice());
-            }
-        }
+        // drop any remaining values at the tail of the source
+        src.drop_in_place();
+        // but prevent drop of the allocation itself once IntoIter goes out of scope
+        src.forget_in_place();
 
         let vec = unsafe {
             let len = dst.offset_from(src_buf) as usize;
-            Vec::from_raw_parts(src.buf.as_ptr(), len, src.cap)
+            Vec::from_raw_parts(src_buf, len, cap)
         };
-        // prevent drop of the underlying storage by turning the IntoIter into
-        // the equivalent of Vec::new().into_iter()
-        src.cap = 0;
-        src.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
-        src.ptr = src.buf.as_ptr();
-        src.end = src.buf.as_ptr();
 
         vec
     }
@@ -2839,6 +2831,24 @@ impl<T> IntoIter<T> {
     fn as_raw_mut_slice(&mut self) -> *mut [T] {
         ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len())
     }
+
+    fn drop_in_place(&mut self) {
+        if mem::needs_drop::<T>() {
+            unsafe {
+                ptr::drop_in_place(self.as_mut_slice());
+            }
+        }
+        self.ptr = self.end;
+    }
+
+    /// Relinquishes the backing allocation, equivalent to
+    /// `ptr::write(&mut self, Vec::new().into_iter())`
+    fn forget_in_place(&mut self) {
+        self.cap = 0;
+        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
+        self.ptr = self.buf.as_ptr();
+        self.end = self.buf.as_ptr();
+    }
 }
 
 #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]