From f1580f33a3ea7f198e3d385451eb992d277f59fa Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sat, 8 Feb 2025 13:34:52 +0900 Subject: [PATCH 1/5] Implement `Random` for array Implement `Random` for `[T; N]`, where `Random` is implemented for `T`. --- library/core/src/array/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 28329bb090845..5e4f1694f544f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -17,6 +17,7 @@ use crate::ops::{ ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, }; use crate::ptr::{null, null_mut}; +use crate::random::{Random, RandomSource}; use crate::slice::{Iter, IterMut}; mod ascii; @@ -426,6 +427,18 @@ impl Clone for [T; N] { } } +#[unstable(feature = "random", issue = "130703")] +impl Random for [T; N] { + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + let mut buf = [const { MaybeUninit::uninit() }; N]; + for elem in &mut buf { + elem.write(T::random(source)); + } + // SAFETY: all elements of the array were initialized. + unsafe { mem::transmute_copy(&buf) } + } +} + trait SpecArrayClone: Clone { fn clone(array: &[Self; N]) -> [Self; N]; } From 80d776e0fe6819077d78ecb34e041895477f13aa Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sun, 9 Feb 2025 09:02:09 +0900 Subject: [PATCH 2/5] Change to use `array::from_fn` --- library/core/src/array/mod.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 5e4f1694f544f..17b5f4bb01ba9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -430,12 +430,7 @@ impl Clone for [T; N] { #[unstable(feature = "random", issue = "130703")] impl Random for [T; N] { fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { - let mut buf = [const { MaybeUninit::uninit() }; N]; - for elem in &mut buf { - elem.write(T::random(source)); - } - // SAFETY: all elements of the array were initialized. - unsafe { mem::transmute_copy(&buf) } + from_fn(|_| T::random(source)) } } From 5435be8d9d82c6848617ed2ce5693ad0a19e9c24 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sun, 9 Feb 2025 10:47:55 +0900 Subject: [PATCH 3/5] Add specialization `Random` for integer arrays Implements specialized `Random` for the array whose elements are integer primitives. This reduces the number of system calls. --- library/core/src/array/mod.rs | 38 +++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 17b5f4bb01ba9..1b18379ac036c 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -18,7 +18,7 @@ use crate::ops::{ }; use crate::ptr::{null, null_mut}; use crate::random::{Random, RandomSource}; -use crate::slice::{Iter, IterMut}; +use crate::slice::{self, Iter, IterMut}; mod ascii; mod drain; @@ -429,11 +429,45 @@ impl Clone for [T; N] { #[unstable(feature = "random", issue = "130703")] impl Random for [T; N] { - fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + default fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { from_fn(|_| T::random(source)) } } +macro_rules! impl_random_for_integer_array { + ($t:ty) => { + #[unstable(feature = "random", issue = "130703")] + impl Random for [$t; N] { + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + let mut buf = [const { MaybeUninit::<$t>::uninit() }; N]; + // SAFETY: all elements in the buffer were initialized with + // random bytes. + unsafe { + let bytes = slice::from_raw_parts_mut( + &raw mut buf as *mut u8, + N * (<$t>::BITS as usize / 8), + ); + source.fill_bytes(bytes); + mem::transmute_copy(&buf) + } + } + } + }; +} + +impl_random_for_integer_array!(u8); +impl_random_for_integer_array!(u16); +impl_random_for_integer_array!(u32); +impl_random_for_integer_array!(u64); +impl_random_for_integer_array!(u128); +impl_random_for_integer_array!(usize); +impl_random_for_integer_array!(i8); +impl_random_for_integer_array!(i16); +impl_random_for_integer_array!(i32); +impl_random_for_integer_array!(i64); +impl_random_for_integer_array!(i128); +impl_random_for_integer_array!(isize); + trait SpecArrayClone: Clone { fn clone(array: &[Self; N]) -> [Self; N]; } From b7d7fc6677a18886d973c52d3971bbfbcd2429ec Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sun, 9 Feb 2025 23:26:39 +0900 Subject: [PATCH 4/5] Hide specialized `Random` for array behind private trait --- library/core/src/array/mod.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 1b18379ac036c..7ac46f4997b12 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -429,7 +429,19 @@ impl Clone for [T; N] { #[unstable(feature = "random", issue = "130703")] impl Random for [T; N] { - default fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + SpecArrayRandom::random(source) + } +} + +#[unstable(feature = "random", issue = "130703")] +trait SpecArrayRandom: Sized { + fn random(source: &mut (impl RandomSource + ?Sized)) -> [Self; N]; +} + +#[unstable(feature = "random", issue = "130703")] +impl SpecArrayRandom for T { + default fn random(source: &mut (impl RandomSource + ?Sized)) -> [T; N] { from_fn(|_| T::random(source)) } } @@ -437,8 +449,8 @@ impl Random for [T; N] { macro_rules! impl_random_for_integer_array { ($t:ty) => { #[unstable(feature = "random", issue = "130703")] - impl Random for [$t; N] { - fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { + impl SpecArrayRandom for $t { + fn random(source: &mut (impl RandomSource + ?Sized)) -> [$t; N] { let mut buf = [const { MaybeUninit::<$t>::uninit() }; N]; // SAFETY: all elements in the buffer were initialized with // random bytes. From b33af51d6edeb28b2897431ae12fa5e5ac364612 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Fri, 28 Feb 2025 22:27:45 +0900 Subject: [PATCH 5/5] Apply suggestions from code review --- library/core/src/array/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 7ac46f4997b12..6ea4b2f533b61 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -18,7 +18,7 @@ use crate::ops::{ }; use crate::ptr::{null, null_mut}; use crate::random::{Random, RandomSource}; -use crate::slice::{self, Iter, IterMut}; +use crate::slice::{Iter, IterMut}; mod ascii; mod drain; @@ -455,12 +455,9 @@ macro_rules! impl_random_for_integer_array { // SAFETY: all elements in the buffer were initialized with // random bytes. unsafe { - let bytes = slice::from_raw_parts_mut( - &raw mut buf as *mut u8, - N * (<$t>::BITS as usize / 8), - ); + let bytes = buf.as_bytes_mut().assume_init_mut(); source.fill_bytes(bytes); - mem::transmute_copy(&buf) + MaybeUninit::array_assume_init(buf) } } }