From 3d4f8b1f450e883b18c17bc56a1de575dd06f148 Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 19 Dec 2023 19:30:52 +0100 Subject: [PATCH 1/6] core: implement `array::repeat` --- library/core/src/array/mod.rs | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 2569ce237077e..fdb707bf51d39 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -10,6 +10,7 @@ use crate::convert::Infallible; use crate::error::Error; use crate::fmt; use crate::hash::{self, Hash}; +use crate::intrinsics::transmute_unchecked; use crate::iter::UncheckedIterator; use crate::mem::{self, MaybeUninit}; use crate::ops::{ @@ -27,6 +28,41 @@ pub(crate) use drain::drain_array_with; #[stable(feature = "array_value_iter", since = "1.51.0")] pub use iter::IntoIter; +/// Creates an array of type `[T; N]` by repeatedly cloning a value. +/// +/// The value will be used as the last element of the resulting array, so it +/// will be cloned N - 1 times. If N is zero, the value will be dropped. +/// +/// # Example +/// +/// Creating muliple copies of a string: +/// ```rust +/// #![feature(array_repeat)] +/// +/// use std::array; +/// +/// let string = "Hello there!".to_string(); +/// let strings = array::repeat(string); +/// assert_eq!(strings, ["Hello there!", "Hello there!"]); +/// ``` +#[inline] +#[unstable(feature = "array_repeat", issue = "none")] +pub fn repeat(val: T) -> [T; N] { + match N { + // SAFETY: we know N to be 0 at this point. + 0 => unsafe { transmute_unchecked::<[T; 0], [T; N]>([]) }, + // SAFETY: we know N to be 1 at this point. + 1 => unsafe { transmute_unchecked::<[T; 1], [T; N]>([val]) }, + _ => { + let mut array = MaybeUninit::uninit_array::(); + try_from_fn_erased(&mut array[..N - 1], NeverShortCircuit::wrap_mut_1(|_| val.clone())); + array[N - 1].write(val); + // SAFETY: all elements were initialized. + unsafe { MaybeUninit::array_assume_init(array) } + } + } +} + /// Creates an array of type [T; N], where each element `T` is the returned value from `cb` /// using that element's index. /// From 8aa24572f08e84ac649f69d02eb74439b6b448ba Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 20 Dec 2023 00:13:22 +0100 Subject: [PATCH 2/6] core: implement `UncheckedIterator` for `RepeatN` --- library/core/src/iter/sources/repeat_n.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 8224e4b12a0eb..8390dab8e543e 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -1,4 +1,4 @@ -use crate::iter::{FusedIterator, TrustedLen}; +use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator}; use crate::mem::ManuallyDrop; use crate::num::NonZero; @@ -193,3 +193,5 @@ impl FusedIterator for RepeatN {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RepeatN {} +#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")] +impl UncheckedIterator for RepeatN {} From 39a918002e67e21330ac9103d471dc1701382c31 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 20 Dec 2023 00:14:25 +0100 Subject: [PATCH 3/6] core: simplify implementation of `array::repeat`, address other nits --- library/core/src/array/mod.rs | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index fdb707bf51d39..63b79d5256da2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -10,8 +10,7 @@ use crate::convert::Infallible; use crate::error::Error; use crate::fmt; use crate::hash::{self, Hash}; -use crate::intrinsics::transmute_unchecked; -use crate::iter::UncheckedIterator; +use crate::iter::{repeat_n, UncheckedIterator}; use crate::mem::{self, MaybeUninit}; use crate::ops::{ ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, @@ -30,12 +29,16 @@ pub use iter::IntoIter; /// Creates an array of type `[T; N]` by repeatedly cloning a value. /// -/// The value will be used as the last element of the resulting array, so it -/// will be cloned N - 1 times. If N is zero, the value will be dropped. +/// This is the same as `[val; N]`, but it also works for types that do not +/// implement [`Copy`]. +/// +/// The provided value will be used as an element of the resulting array and +/// will be cloned N - 1 times to fill up the rest. If N is zero, the value +/// will be dropped. /// /// # Example /// -/// Creating muliple copies of a string: +/// Creating muliple copies of a `String`: /// ```rust /// #![feature(array_repeat)] /// @@ -48,19 +51,7 @@ pub use iter::IntoIter; #[inline] #[unstable(feature = "array_repeat", issue = "none")] pub fn repeat(val: T) -> [T; N] { - match N { - // SAFETY: we know N to be 0 at this point. - 0 => unsafe { transmute_unchecked::<[T; 0], [T; N]>([]) }, - // SAFETY: we know N to be 1 at this point. - 1 => unsafe { transmute_unchecked::<[T; 1], [T; N]>([val]) }, - _ => { - let mut array = MaybeUninit::uninit_array::(); - try_from_fn_erased(&mut array[..N - 1], NeverShortCircuit::wrap_mut_1(|_| val.clone())); - array[N - 1].write(val); - // SAFETY: all elements were initialized. - unsafe { MaybeUninit::array_assume_init(array) } - } - } + from_trusted_iterator(repeat_n(val, N)) } /// Creates an array of type [T; N], where each element `T` is the returned value from `cb` From 1a8b0d7c53b62825cbe1319d6ff06e12f4dba187 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 5 Jan 2024 12:43:01 +0100 Subject: [PATCH 4/6] add codegen test for `array::repeat` --- tests/codegen/array-repeat.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/codegen/array-repeat.rs diff --git a/tests/codegen/array-repeat.rs b/tests/codegen/array-repeat.rs new file mode 100644 index 0000000000000..d4cdb054ad810 --- /dev/null +++ b/tests/codegen/array-repeat.rs @@ -0,0 +1,15 @@ +// compile-flags: -O + +#![crate_type = "lib"] +#![feature(array_repeat)] + +use std::array::repeat; + +// CHECK-LABEL: @byte_repeat +#[no_mangle] +fn byte_repeat(b: u8) -> [u8; 1024] { + // CHECK-NOT: alloca + // CHECK-NOT: store + // CHECK: memset + repeat(b) +} From e1aacea74dcdd53095af1618e6466ae8475458ac Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 19 Jun 2024 17:48:00 +0200 Subject: [PATCH 5/6] core: add tracking issue for `array::repeat` --- library/core/src/array/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 63b79d5256da2..3e4eadbb7c979 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -49,7 +49,7 @@ pub use iter::IntoIter; /// assert_eq!(strings, ["Hello there!", "Hello there!"]); /// ``` #[inline] -#[unstable(feature = "array_repeat", issue = "none")] +#[unstable(feature = "array_repeat", issue = "126695")] pub fn repeat(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } From 0aa3310a9ac22509f138566398c2e65a777f5967 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 19 Jun 2024 17:48:05 +0200 Subject: [PATCH 6/6] update codegen test for `array::repeat` --- tests/codegen/array-repeat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/array-repeat.rs b/tests/codegen/array-repeat.rs index d4cdb054ad810..b6f3b2e83d3e1 100644 --- a/tests/codegen/array-repeat.rs +++ b/tests/codegen/array-repeat.rs @@ -1,4 +1,4 @@ -// compile-flags: -O +//@ compile-flags: -O #![crate_type = "lib"] #![feature(array_repeat)]