diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 966272ca11549..af10f843fa8b2 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -11,7 +11,9 @@ use crate::cmp::Ordering;
 use crate::convert::{Infallible, TryFrom};
 use crate::fmt;
 use crate::hash::{self, Hash};
+use crate::iter::FromIterator;
 use crate::marker::Unsize;
+use crate::mem::MaybeUninit;
 use crate::slice::{Iter, IterMut};
 
 mod iter;
@@ -188,6 +190,104 @@ impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
     }
 }
 
+/// Return Error of the FromIterator impl for array
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+pub struct FillError<T, const N: usize> {
+    array: [MaybeUninit<T>; N],
+    len: usize,
+}
+
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+impl<T, const N: usize> fmt::Display for FillError<T, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(
+            &format_args!("The iterator only returned {} items, but {} were needed", self.len(), N),
+            f,
+        )
+    }
+}
+
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+impl<T: fmt::Debug, const N: usize> fmt::Debug for FillError<T, N> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("FillError")
+            .field("array", &self.as_slice())
+            .field("len", &self.len())
+            .finish()
+    }
+}
+
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+impl<T, const N: usize> Drop for FillError<T, N> {
+    fn drop(&mut self) {
+        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
+        // of elements that have been initialized and need to be droped
+        unsafe { crate::ptr::drop_in_place(self.as_mut_slice()) }
+    }
+}
+
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+impl<T, const N: usize> FillError<T, N> {
+    fn new() -> Self {
+        Self { array: MaybeUninit::uninit_array(), len: 0 }
+    }
+
+    /// Returns the how many elements were read from the given iterator.
+    pub fn len(&self) -> usize {
+        self.len
+    }
+
+    /// Returns an immutable slice of all initialized elements.
+    pub fn as_slice(&self) -> &[T] {
+        // SAFETY: We know that all elements from 0 to len are properly initialized.
+        unsafe { MaybeUninit::slice_assume_init_ref(&self.array[0..self.len]) }
+    }
+
+    /// Returns a mutable slice of all initialized elements.
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        // SAFETY: We know that all elements from 0 to len are properly initialized.
+        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.array[0..self.len]) }
+    }
+
+    /// Tries to initialize the left-over elements using `iter`.
+    pub fn fill<I: IntoIterator<Item = T>>(mut self, iter: I) -> Result<[T; N], FillError<T, N>> {
+        let mut iter = iter.into_iter();
+
+        for i in self.len..N {
+            if let Some(value) = iter.next() {
+                self.array[i].write(value);
+                self.len += 1;
+            } else {
+                self.len = i;
+                return Err(self);
+            }
+        }
+
+        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
+        // promise:
+        //
+        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
+        // > as `T`.
+        //
+        // The docs even show a transmute from an array of `MaybeUninit<T>` to
+        // an array of `T`.
+        //
+        // With that, this initialization satisfies the invariants.
+        // FIXME: actually use `mem::transmute` here, once it
+        // works with const generics:
+        //     `mem::transmute::<[MaybeUninit<T>; N], [T; N]>(array)`
+        Ok(unsafe { crate::ptr::read(&self.array as *const [MaybeUninit<T>; N] as *const [T; N]) })
+    }
+}
+
+#[unstable(feature = "array_from_iter_impl", issue = "none")]
+impl<T, const N: usize> FromIterator<T> for Result<[T; N], FillError<T, N>> {
+    #[inline]
+    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+        FillError::<T, N>::new().fill(iter)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
     type Item = &'a T;
@@ -403,7 +503,6 @@ impl<T, const N: usize> [T; N] {
     where
         F: FnMut(T) -> U,
     {
-        use crate::mem::MaybeUninit;
         struct Guard<T, const N: usize> {
             dst: *mut T,
             initialized: usize,
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index 89c2a969c28bb..a3a13b94b6169 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -374,3 +374,11 @@ fn cell_allows_array_cycle() {
     b3.a[0].set(Some(&b1));
     b3.a[1].set(Some(&b2));
 }
+
+#[test]
+fn array_collects() {
+    let v = vec![1, 2, 3, 4, 5];
+    let a: [i32; 5] = v.clone().into_iter().collect::<Result<[i32; 5], _>>().unwrap();
+
+    assert_eq!(v[..], a[..]);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 0c4ce867f542d..e13999de41c97 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -60,6 +60,7 @@
 #![feature(unsafe_block_in_unsafe_fn)]
 #![feature(int_bits_const)]
 #![deny(unsafe_op_in_unsafe_fn)]
+#![feature(array_from_iter_impl)]
 
 extern crate test;
 
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 81bbf37637875..0adf229721a52 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -492,6 +492,7 @@ mod prim_pointer {}
 /// Arrays of *any* size implement the following traits if the element type allows it:
 ///
 /// - [`Debug`]
+/// - [`iter::FromIterator`]
 /// - [`IntoIterator`] (implemented for `&[T; N]` and `&mut [T; N]`)
 /// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`]
 /// - [`Hash`]