Change:
I tried this code: I expected to see this happen: Both and should get optimized to just return the input unchanged. Instead, this happened: unwrapcopy get's optimized as espected: unwrapclone fails to get optimized and compiles into a loop: Originally I thought that behavior was caused by the underlying type not implementing Copy but Drop seems to be the actual culprit. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: </p</details
This reminds me of the do-nothing-loop from . That's not quite true, e.g. this also optimizes even though is not : So it's likely due to and the compiler fails to see that the drop can't happen.

Discussion:
#![feature(tuple_trait)] #![feature(unicode_internals)] #![feature(unsize)] <ins> #![feature(unwrap_infallible)] </ins> #![feature(vec_pop_if)] // tidy-alphabetical-end //

inner.cap, inner.buf.cast::<T>(), inner.end as *const T, <del> inner.cap * mem::size_of::<I::Src>() / mem::size_of::<T>(), </del> <ins> // SAFETY: the multiplication can not overflow, since `inner.cap * size_of::<I::SRC>()` is the size of the allocation. inner.cap.unchecked_mul(mem::size_of::<I::Src>()) / mem::size_of::<T>(), </ins> ) };

// - it lets us thread the write pointer through its innards and get it back in the end let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; let sink = <del> self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).unwrap(); </del> <ins> self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).into_ok(); </ins> // iteration succeeded, don't drop head unsafe { ManuallyDrop::new(sink).dst.sub_ptr(dst_buf) } }

}; } <ins> fn fold<B, F>(mut self, mut accum: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B, { if T::IS_ZST { while self.ptr.as_ptr() != self.end.cast_mut() { // SAFETY: we just checked that `self.ptr` is in bounds. let tmp = unsafe { self.ptr.read() }; // See `next` for why we subtract from `end` here. self.end = self.end.wrapping_byte_sub(1); accum = f(accum, tmp); } } else { // SAFETY: `self.end` can only be null if `T` is a ZST. while self.ptr != non_null!(self.end, T) { // SAFETY: we just checked that `self.ptr` is in bounds. let tmp = unsafe { self.ptr.read() }; // SAFETY: the maximum this can be is `self.end`. // Increment `self.ptr` first to avoid double dropping in the event of a panic. self.ptr = unsafe { self.ptr.add(1) }; accum = f(accum, tmp); } } accum } fn try_fold<B, F, R>(&mut self, mut accum: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: core::ops::Try<Output = B>, { if T::IS_ZST { while self.ptr.as_ptr() != self.end.cast_mut() { // SAFETY: we just checked that `self.ptr` is in bounds. let tmp = unsafe { self.ptr.read() }; // See `next` for why we subtract from `end` here. self.end = self.end.wrapping_byte_sub(1); accum = f(accum, tmp)?; } } else { // SAFETY: `self.end` can only be null if `T` is a ZST. while self.ptr != non_null!(self.end, T) { // SAFETY: we just checked that `self.ptr` is in bounds. let tmp = unsafe { self.ptr.read() }; // SAFETY: the maximum this can be is `self.end`. // Increment `self.ptr` first to avoid double dropping in the event of a panic. self.ptr = unsafe { self.ptr.add(1) }; accum = f(accum, tmp)?; } } R::from_output(accum) } </ins> unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item where Self: TrustedRandomAccessNoCoerce,