Add recommend changes to array

Switch from indexing to zip, and also use `write` on `MaybeUninit`.

Add array_map feature to core/src/lib

Attempt to fix issue of no such feature

Update w/ pickfire's review

This changes a couple of names around, adds another small test of variable size,
and hides the rustdoc #![feature(..)].

Fmt doctest

Add suggestions from lcnr
This commit is contained in:
kadmin 2020-08-06 23:36:50 +00:00
parent f6411e4c66
commit 56a651ca15
3 changed files with 21 additions and 15 deletions

View File

@ -372,27 +372,28 @@ impl<T, const N: usize> [T; N] {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// let x = [1,2,3]; /// # #![feature(array_map)]
/// let x = [1, 2, 3];
/// let y = x.map(|v| v + 1); /// let y = x.map(|v| v + 1);
/// assert_eq!(y, [2,3,4]); /// assert_eq!(y, [2, 3, 4]);
/// ``` /// ```
#[unstable(feature = "array_map", issue = "77777")] #[unstable(feature = "array_map", issue = "77777")]
pub fn map<F, S>(self, mut f: F) -> [S; N] pub fn map<F, U>(self, mut f: F) -> [U; N]
where where
F: FnMut(T) -> S, F: FnMut(T) -> U,
{ {
use crate::mem::MaybeUninit; use crate::mem::MaybeUninit;
struct Guard<T, const N: usize> { struct Guard<T, const N: usize> {
dst: *mut T, dst: *mut T,
curr_init: usize, initialized: usize,
} }
impl<T, const N: usize> Drop for Guard<T, N> { impl<T, const N: usize> Drop for Guard<T, N> {
fn drop(&mut self) { fn drop(&mut self) {
debug_assert!(self.curr_init <= N); debug_assert!(self.initialized <= N);
let initialized_part = let initialized_part =
crate::ptr::slice_from_raw_parts_mut(self.dst, self.curr_init); crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
// SAFETY: this raw slice will contain only initialized objects // SAFETY: this raw slice will contain only initialized objects
// that's why, it is allowed to drop it. // that's why, it is allowed to drop it.
unsafe { unsafe {
@ -401,16 +402,16 @@ impl<T, const N: usize> [T; N] {
} }
} }
let mut dst = MaybeUninit::uninit_array::<N>(); let mut dst = MaybeUninit::uninit_array::<N>();
let mut guard: Guard<S, N> = Guard { dst: &mut dst as *mut _ as *mut S, curr_init: 0 }; let mut guard: Guard<U, N> = Guard { dst: &mut dst as *mut _ as *mut U, initialized: 0 };
for (i, e) in IntoIter::new(self).enumerate() { for (src, dst) in IntoIter::new(self).zip(&mut dst) {
dst[i] = MaybeUninit::new(f(e)); dst.write(f(src));
guard.curr_init += 1; guard.initialized += 1;
} }
// FIXME convert to crate::mem::transmute when works with generics // FIXME: Convert to crate::mem::transmute once it works with generics.
// unsafe { crate::mem::transmute::<[MaybeUninit<S>; N], [S; N]>(dst) } // unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
crate::mem::forget(guard); crate::mem::forget(guard);
// SAFETY: At this point we've properly initialized the whole array // SAFETY: At this point we've properly initialized the whole array
// and we just need to cast it to the correct type // and we just need to cast it to the correct type.
unsafe { (&mut dst as *mut _ as *mut [S; N]).read() } unsafe { (&mut dst as *mut _ as *mut [U; N]).read() }
} }
} }

View File

@ -145,6 +145,7 @@
#![feature(abi_unadjusted)] #![feature(abi_unadjusted)]
#![feature(adx_target_feature)] #![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_extra)]
#![feature(external_doc)] #![feature(external_doc)]
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(const_caller_location)] #![feature(const_caller_location)]

View File

@ -296,4 +296,8 @@ fn array_map() {
let a = [1, 2, 3]; let a = [1, 2, 3];
let b = a.map(|v| v + 1); let b = a.map(|v| v + 1);
assert_eq!(b, [2, 3, 4]); assert_eq!(b, [2, 3, 4]);
let a = [1u8, 2, 3];
let b = a.map(|v| v as u64);
assert_eq!(b, [1, 2, 3]);
} }