Rollup merge of #128530 - scottmcm:repeat-n-unchecked, r=joboet
Implement `UncheckedIterator` directly for `RepeatN` This just pulls the code out of `next` into `next_unchecked`, rather than making the `Some` and `unwrap_unchecked`ing it. And while I was touching it, I added a codegen test that `array::repeat` for something that's just `Clone`, not `Copy`, still ends up optimizing to the same thing as `[x; n]`: <https://rust.godbolt.org/z/YY3a5ajMW>.
This commit is contained in:
commit
53a56190af
@ -114,19 +114,12 @@ impl<A: Clone> Iterator for RepeatN<A> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<A> {
|
fn next(&mut self) -> Option<A> {
|
||||||
if self.count == 0 {
|
if self.count > 0 {
|
||||||
return None;
|
// SAFETY: Just checked it's not empty
|
||||||
}
|
unsafe { Some(self.next_unchecked()) }
|
||||||
|
|
||||||
self.count -= 1;
|
|
||||||
Some(if self.count == 0 {
|
|
||||||
// SAFETY: the check above ensured that the count used to be non-zero,
|
|
||||||
// so element hasn't been dropped yet, and we just lowered the count to
|
|
||||||
// zero so it won't be dropped later, and thus it's okay to take it here.
|
|
||||||
unsafe { ManuallyDrop::take(&mut self.element) }
|
|
||||||
} else {
|
} else {
|
||||||
A::clone(&self.element)
|
None
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -194,4 +187,18 @@ impl<A: Clone> FusedIterator for RepeatN<A> {}
|
|||||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||||
unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
|
unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
|
||||||
#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
|
#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
|
||||||
impl<A: Clone> UncheckedIterator for RepeatN<A> {}
|
impl<A: Clone> UncheckedIterator for RepeatN<A> {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn next_unchecked(&mut self) -> Self::Item {
|
||||||
|
// SAFETY: The caller promised the iterator isn't empty
|
||||||
|
self.count = unsafe { self.count.unchecked_sub(1) };
|
||||||
|
if self.count == 0 {
|
||||||
|
// SAFETY: the check above ensured that the count used to be non-zero,
|
||||||
|
// so element hasn't been dropped yet, and we just lowered the count to
|
||||||
|
// zero so it won't be dropped later, and thus it's okay to take it here.
|
||||||
|
unsafe { ManuallyDrop::take(&mut self.element) }
|
||||||
|
} else {
|
||||||
|
A::clone(&self.element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
//@ compile-flags: -O
|
//@ compile-flags: -C opt-level=3
|
||||||
//@ only-x86_64
|
//@ only-x86_64
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(iter_repeat_n)]
|
#![feature(iter_repeat_n)]
|
||||||
|
#![feature(array_repeat)]
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct NotCopy(u16);
|
pub struct NotCopy(u16);
|
||||||
@ -54,3 +55,15 @@ pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
|
|||||||
v.extend(std::iter::repeat_n(42_u8, n));
|
v.extend(std::iter::repeat_n(42_u8, n));
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Array repeat uses `RepeatN::next_unchecked` internally,
|
||||||
|
// so also check that the distinction disappears there.
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @array_repeat_not_copy
|
||||||
|
pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] {
|
||||||
|
// CHECK: insertelement {{.+}} i16 %item
|
||||||
|
// CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer
|
||||||
|
// CHECK: store <8 x i16>
|
||||||
|
std::array::repeat(item)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user