Skip to content

Commit

Permalink
Auto merge of rust-lang#120952 - saethlin:vec-into-iter, r=<try>
Browse files Browse the repository at this point in the history
Don't use mem::zeroed in vec::IntoIter

`mem::zeroed` is not a trivial function. Maybe it was once, but now it involves multiple locals, copies, and an intrinsic that gets monomorphized into a call to `panic_nounwind` for iterators of types like `Vec<&T>`. Of course all that complexity is trivially optimized out, but generating a bunch of IR where we don't need to just so we can optimize it away later is silly.

r? `@ghost`
  • Loading branch information
bors committed Feb 12, 2024
2 parents 520b0b2 + 78a4d71 commit 0183a22
Showing 1 changed file with 25 additions and 36 deletions.
61 changes: 25 additions & 36 deletions library/alloc/src/vec/into_iter.rs
Expand Up @@ -11,7 +11,7 @@ use core::iter::{
TrustedRandomAccessNoCoerce,
};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::num::NonZeroUsize;
#[cfg(not(no_global_oom_handling))]
use core::ops::Deref;
Expand Down Expand Up @@ -200,27 +200,23 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {

#[inline]
fn next(&mut self) -> Option<T> {
if T::IS_ZST {
if self.ptr.as_ptr() == self.end as *mut _ {
None
} else {
// `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
// reducing the `end`.
self.end = self.end.wrapping_byte_sub(1);

// Make up a value of this ZST.
Some(unsafe { mem::zeroed() })
let ptr = if T::IS_ZST {
if self.ptr.as_ptr() == self.end as *mut T {
return None;
}
// `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
// reducing the `end`.
self.end = self.end.wrapping_byte_sub(1);
self.ptr
} else {
if self.ptr == non_null!(self.end, T) {
None
} else {
let old = self.ptr;
self.ptr = unsafe { old.add(1) };

Some(unsafe { ptr::read(old.as_ptr()) })
if self.ptr == unsafe { NonNull::new_unchecked(self.end as *mut T) } {
return None;
}
}
let old = self.ptr;
self.ptr = unsafe { old.add(1) };
old
};
Some(unsafe { ptr.read() })
}

#[inline]
Expand Down Expand Up @@ -305,32 +301,25 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
// Also note the implementation of `Self: TrustedRandomAccess` requires
// that `T: Copy` so reading elements from the buffer doesn't invalidate
// them for `Drop`.
unsafe { if T::IS_ZST { mem::zeroed() } else { self.ptr.add(i).read() } }
unsafe { self.ptr.add(i).read() }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
#[inline]
fn next_back(&mut self) -> Option<T> {
if self.ptr.as_ptr() == self.end as *mut _ {
return None;
}
if T::IS_ZST {
if self.end as *mut _ == self.ptr.as_ptr() {
None
} else {
// See above for why 'ptr.offset' isn't used
self.end = self.end.wrapping_byte_sub(1);

// Make up a value of this ZST.
Some(unsafe { mem::zeroed() })
}
// See above for why 'ptr.offset' isn't used
self.end = self.end.wrapping_byte_sub(1);
Some(unsafe { ptr::read(self.ptr.as_ptr()) })
} else {
if non_null!(self.end, T) == self.ptr {
None
} else {
let new_end = unsafe { non_null!(self.end, T).sub(1) };
*non_null!(mut self.end, T) = new_end;

Some(unsafe { ptr::read(new_end.as_ptr()) })
unsafe {
self.end = self.end.sub(1);
Some(ptr::read(self.end))
}
}
}
Expand Down

0 comments on commit 0183a22

Please sign in to comment.