Skip to content

Const generics: array support #939

@dhardy

Description

@dhardy

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:

  1. Use std::mem::MaybeUninit. This should work with code like this; currently it doesn't (I believe because of const_generics bugs):

    #[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) }
        }
    }
  2. Use an extra bound like T: Default to allow construction of a temporary, then generate elt-by-elt.

  3. If somehow Rust were to support FromIterator for array types, we could use iter::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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions