///
/// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
/// (at least, it's highly likely to be incorrect if it wasn't).
- /// * `ptr`'s `T` needs to have the same size and alignment as it was allocated with.
+ /// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
+ /// (`T` having a less strict alignment is not sufficient, the alignment really
+ /// needs to be equal to satsify the [`dealloc`] requirement that memory must be
+ /// allocated and deallocated with the same layout.)
/// * `length` needs to be less than or equal to `capacity`.
/// * `capacity` needs to be the capacity that the pointer was allocated with.
///
/// function.
///
/// [`String`]: ../../std/string/struct.String.html
+ /// [`dealloc`]: ../../alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
///
/// # Examples
///
unsafe impl<#[may_dangle] T> Drop for IntoIter<T> {
fn drop(&mut self) {
// destroy the remaining elements
- for _x in self.by_ref() {}
+ unsafe {
+ ptr::drop_in_place(self.as_mut_slice());
+ }
// RawVec handles deallocation
let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) };
#[stable(feature = "drain", since = "1.6.0")]
impl<T> Drop for Drain<'_, T> {
fn drop(&mut self) {
- // exhaust self first
- self.for_each(drop);
+ /// Continues dropping the remaining elements in the `Drain`, then moves back the
+ /// un-`Drain`ed elements to restore the original `Vec`.
+ struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
- if self.tail_len > 0 {
- unsafe {
- let source_vec = self.vec.as_mut();
- // memmove back untouched tail, update to new length
- let start = source_vec.len();
- let tail = self.tail_start;
- if tail != start {
- let src = source_vec.as_ptr().add(tail);
- let dst = source_vec.as_mut_ptr().add(start);
- ptr::copy(src, dst, self.tail_len);
+ impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> {
+ fn drop(&mut self) {
+ // Continue the same loop we have below. If the loop already finished, this does
+ // nothing.
+ self.0.for_each(drop);
+
+ if self.0.tail_len > 0 {
+ unsafe {
+ let source_vec = self.0.vec.as_mut();
+ // memmove back untouched tail, update to new length
+ let start = source_vec.len();
+ let tail = self.0.tail_start;
+ if tail != start {
+ let src = source_vec.as_ptr().add(tail);
+ let dst = source_vec.as_mut_ptr().add(start);
+ ptr::copy(src, dst, self.0.tail_len);
+ }
+ source_vec.set_len(start + self.0.tail_len);
+ }
}
- source_vec.set_len(start + self.tail_len);
}
}
+
+ // exhaust self first
+ while let Some(item) = self.next() {
+ let guard = DropGuard(self);
+ drop(item);
+ mem::forget(guard);
+ }
+
+ // Drop a `DropGuard` to move back the non-drained tail of `self`.
+ DropGuard(self);
}
}