Change:
<!-- Thank you for filing a bug report! Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. --I'm trying out the allocator api with the goal of being able to track memory usage for parts of a program: I expected this to work (and print 0 at the end), but instead it fails by freeing an invalid pointer: Running with miri gives a bit more context:
This seems to be a problem with the implementation of because if I do: There is no crash and no Miri error, this to me indicate that there is a problem in the implementation of . Another interesting things is the message I have locally , I don't know what it means but it's certainly interesting. label +T-libs +I-unsound
The drop guard used in the implementation of IntoIter makes a raw copy of an allocator when reconstructing RawVec. The allocator is then dropped twice, once by RawVec drop and second time by IntoIter drop. cc .
Minimal reproduction of problem: Prints:

Discussion:
FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; <del> use core::mem::{self}; </del> <ins> use core::mem::{self, ManuallyDrop}; use core::ops::Deref; </ins> use core::ptr::{self, NonNull}; use core::slice::{self};

pub(super) buf: NonNull<T>, pub(super) phantom: PhantomData<T>, pub(super) cap: usize, <del> pub(super) alloc: A, </del> <ins> // the drop impl reconstructs a RawVec from buf, cap and alloc // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop pub(super) alloc: ManuallyDrop<A>, </ins> pub(super) ptr: *const T, pub(super) end: *const T, }

impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> { #[cfg(not(test))] fn clone(&self) -> Self { <del> self.as_slice().to_vec_in(self.alloc.clone()).into_iter() </del> <ins> self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter() </ins> } #[cfg(test)] fn clone(&self) -> Self { <del> crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() </del> <ins> crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter() </ins> } }

impl<T, A: Allocator> Drop for DropGuard<'_, T, A> { fn drop(&mut self) { unsafe { <del> // `IntoIter::alloc` is not used anymore after this let alloc = ptr::read(&self.0.alloc); </del> <ins> // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec let alloc = ManuallyDrop::take(&mut self.0.alloc); </ins> // RawVec handles deallocation let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); }

fn into_iter(self) -> IntoIter<T, A> { unsafe { let mut me = ManuallyDrop::new(self); <del> let alloc = ptr::read(me.allocator()); </del> <ins> let alloc = ManuallyDrop::new(ptr::read(me.allocator())); </ins> let begin = me.as_mut_ptr(); let end = if mem::size_of::<T>() == 0 { arith_offset(begin as *const i8, me.len() as isize) as *const T

<ins> use core::alloc::{Allocator, Layout}; use core::ptr::NonNull; use std::alloc::System; </ins> use std::assert_matches::assert_matches; use std::borrow::Cow; use std::cell::Cell;

} #[test] <ins> fn test_into_iter_drop_allocator() { struct ReferenceCountedAllocator<'a>(DropCounter<'a>); unsafe impl Allocator for ReferenceCountedAllocator<'_> { fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> { System.allocate(layout) } unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { System.deallocate(ptr, layout) } } let mut drop_count = 0; let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); let _ = Vec::<u32, _>::new_in(allocator); assert_eq!(drop_count, 1); let allocator = ReferenceCountedAllocator(DropCounter { count: &mut drop_count }); let _ = Vec::<u32, _>::new_in(allocator).into_iter(); assert_eq!(drop_count, 2); } #[test] </ins> fn test_from_iter_specialization() { let src: Vec<usize> = vec![0usize; 1]; let srcptr = src.as_ptr();