-
-
Notifications
You must be signed in to change notification settings - Fork 480
Description
We already support generating [T; N] for Standard where T supports Standard and N ≤ 32 via a macro. It would be nice to replace this with a more generic implementation using const_generics.
There is a catch: our macro generates arrays via this syntax: [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*], but there is no equivalent const-generics literal. This leaves only a couple of options:
-
Use
std::mem::MaybeUninit. This should work with code like this; currently it doesn't (I believe because ofconst_genericsbugs):#[cfg(feature = "const_generics")] impl<T, const N: usize> Distribution<[T; N]> for Standard where Standard: Distribution<T> { #[inline] fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> [T; N] { // We cannot have a safe implementation without some extra bound // allowing construction, e.g. `T: Default`, thus we use MaybeUninit. use core::mem::{MaybeUninit, transmute}; // Use MaybeUninit as in element-by-element array example: // https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element let mut r: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() }; for elem in &mut r[..] { *elem = MaybeUninit::new(rng.gen::<T>()); } unsafe { transmute::<[MaybeUninit<T>; N], [T; N]>(r) } } }
-
Use an extra bound like
T: Defaultto allow construction of a temporary, then generate elt-by-elt. -
If somehow Rust were to support
FromIteratorfor array types, we could useiter::repeat(...).take(N).collect()— but I don't expect to see this happen any time soon (if ever).
Probably eventually we'll go for option (1), though it's a shame we'll need the unsafe code. For now, we do nothing.