about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/array/mod.rs53
-rw-r--r--src/librustc_hir/lang_items.rs1
2 files changed, 54 insertions, 0 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index c0bf3833b9c..b549cd8959f 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -364,3 +364,56 @@ macro_rules! array_impl_default {
 }
 
 array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
+
+#[cfg(not(bootstrap))]
+#[lang = "array"]
+impl<T, const N: usize> [T; N] {
+    /// Returns an array of the same size as self, with `f` applied to each element.
+    ///
+    /// # Examples
+    /// ```
+    /// let x = [1,2,3];
+    /// let y = x.map(|v| v + 1);
+    /// assert_eq!(y, [2,3,4]);
+    /// ```
+    #[unstable(feature = "array_map", issue = "77777")]
+    fn map<F, S>(self, f: F) -> [S; N]
+    where
+        F: FnMut(T) -> S,
+    {
+        use crate::mem::MaybeUninit;
+        struct Guard<T, const N: usize> {
+            dst: *mut T,
+            curr_init: usize,
+        }
+
+        impl<T, const N: usize> Guard<T, N> {
+            fn new(dst: &mut [MaybeUninit<T>; N]) -> Self {
+                Guard { dst: dst as *mut _ as *mut T, curr_init: 0 }
+            }
+        }
+
+        impl<T, const N: usize> Drop for Guard<T, N> {
+            fn drop(&mut self) {
+                debug_assert!(self.curr_init <= N);
+
+                let initialized_part =
+                    crate::ptr::slice_from_raw_parts_mut(self.dst, self.curr_init);
+                // SAFETY: this raw slice will contain only initialized objects
+                // that's why, it is allowed to drop it.
+                unsafe {
+                    crate::ptr::drop_in_place(initialized_part);
+                }
+            }
+        }
+        let dst = MaybeUninit::uninit_array::<N>();
+        let mut guard = Guard::new(&mut dst);
+        for (i, e) in self.into_iter().enumerate() {
+            dst[i] = MaybeUninit::new(f(e));
+            guard.curr_init += 1;
+        }
+        // FIXME convert to crate::mem::transmute when works with generics
+        // unsafe { crate::mem::transmute::<[MaybeUninit<S>; N], [S; N]>(dst) }
+        unsafe { (&mut dst as *mut _ as *mut [S; N]).read() }
+    }
+}
diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs
index 7f473a45848..2f7edeb405f 100644
--- a/src/librustc_hir/lang_items.rs
+++ b/src/librustc_hir/lang_items.rs
@@ -165,6 +165,7 @@ language_item_table! {
     BoolImplItem,                  sym::bool,               bool_impl,               Target::Impl;
     CharImplItem,                  sym::char,               char_impl,               Target::Impl;
     StrImplItem,                   sym::str,                str_impl,                Target::Impl;
+    ArrayImplItem,                 sym::array,              array_impl,              Target::Impl;
     SliceImplItem,                 sym::slice,              slice_impl,              Target::Impl;
     SliceU8ImplItem,               sym::slice_u8,           slice_u8_impl,           Target::Impl;
     StrAllocImplItem,              sym::str_alloc,          str_alloc_impl,          Target::Impl;