Repository: rayon-rs/rayon
Pull request #837 (2021-03-26 19:51:40)

impl IntoParallelIterator for arrays
This requires Rust 1.51, as tested in the build script.


Patch:
diff --git a/build.rs b/build.rs
index 70e301b..e52e326 100644
--- a/build.rs
+++ b/build.rs
@@ -3,4 +3,7 @@ fn main() {
     if ac.probe_expression("(0..10).step_by(2).rev()") {
         autocfg::emit("step_by");
     }
+    if ac.probe_expression("{ fn foo<const N: usize>() {} }") {
+        autocfg::emit("min_const_generics");
+    }
 }
diff --git a/src/array.rs b/src/array.rs
new file mode 100644
index 0000000..7922cd6
--- /dev/null
+++ b/src/array.rs
@@ -0,0 +1,90 @@
+#![cfg(min_const_generics)]
+//! Parallel iterator types for [arrays] (`[T; N]`)
+//!
+//! You will rarely need to interact with this module directly unless you need
+//! to name one of the iterator types.
+//!
+//! Everything in this module requires const generics, stabilized in Rust 1.51.
+//!
+//! [arrays]: https://doc.rust-lang.org/std/primitive.array.html
+
+use crate::iter::plumbing::*;
+use crate::iter::*;
+use crate::slice::{Iter, IterMut};
+use crate::vec::DrainProducer;
+use std::mem::ManuallyDrop;
+
+/// This implementation requires const generics, stabilized in Rust 1.51.
+impl<'data, T: Sync + 'data, const N: usize> IntoParallelIterator for &'data [T; N] {
+    type Item = &'data T;
+    type Iter = Iter<'data, T>;
+
+    fn into_par_iter(self) -> Self::Iter {
+        <&[T]>::into_par_iter(self)
+    }
+}
+
+/// This implementation requires const generics, stabilized in Rust 1.51.
+impl<'data, T: Send + 'data, const N: usize> IntoParallelIterator for &'data mut [T; N] {
+    type Item = &'data mut T;
+    type Iter = IterMut<'data, T>;
+
+    fn into_par_iter(self) -> Self::Iter {
+        <&mut [T]>::into_par_iter(self)
+    }
+}
+
+/// This implementation requires const generics, stabilized in Rust 1.51.
+impl<T: Send, const N: usize> IntoParallelIterator for [T; N] {
+    type Item = T;
+    type Iter = IntoIter<T, N>;
+
+    fn into_par_iter(self) -> Self::Iter {
+        IntoIter { array: self }
+    }
+}
+
+/// Parallel iterator that moves out of an array.
+#[derive(Debug, Clone)]
+pub struct IntoIter<T: Send, const N: usize> {
+    array: [T; N],
+}
+
+impl<T: Send, const N: usize> ParallelIterator for IntoIter<T, N> {
+    type Item = T;
+
+    fn drive_unindexed<C>(self, consumer: C) -> C::Result
+    where
+        C: UnindexedConsumer<Self::Item>,
+    {
+        bridge(self, consumer)
+    }
+
+    fn opt_len(&self) -> Option<usize> {
+        Some(N)
+    }
+}
+
+impl<T: Send, const N: usize> IndexedParallelIterator for IntoIter<T, N> {
+    fn drive<C>(self, consumer: C) -> C::Result
+    where
+        C: Consumer<Self::Item>,
+    {
+        bridge(self, consumer)
+    }
+
+    fn len(&self) -> usize {
+        N
+    }
+
+    fn with_producer<CB>(self, callback: CB) -> CB::Output
+    where
+        CB: ProducerCallback<Self::Item>,
+    {
+        unsafe {
+            // Drain every item, and then the local array can just fall out of scope.
+            let mut array = ManuallyDrop::new(self.array);
+            callback.callback(DrainProducer::new(&mut *array))
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index d5d0314..8931cfc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -91,6 +91,7 @@ mod private;
 
 mod split_producer;
 
+pub mod array;
 pub mod collections;
 pub mod iter;
 pub mod option;
diff --git a/src/slice/mod.rs b/src/slice/mod.rs
index b80125f..d47b0d3 100644
--- a/src/slice/mod.rs
+++ b/src/slice/mod.rs
@@ -470,15 +470,6 @@ impl<'data, T: Sync + 'data> IntoParallelIterator for &'data [T] {
     }
 }
 
-impl<'data, T: Sync + 'data> IntoParallelIterator for &'data Vec<T> {
-    type Item = &'data T;
-    type Iter = Iter<'data, T>;
-
-    fn into_par_iter(self) -> Self::Iter {
-        Iter { slice: self }
-    }
-}
-
 impl<'data, T: Send + 'data> IntoParallelIterator for &'data mut [T] {
     type Item = &'data mut T;
     type Iter = IterMut<'data, T>;
@@ -488,15 +479,6 @@ impl<'data, T: Send + 'data> IntoParallelIterator for &'data mut [T] {
     }
 }
 
-impl<'data, T: Send + 'data> IntoParallelIterator for &'data mut Vec<T> {
-    type Item = &'data mut T;
-    type Iter = IterMut<'data, T>;
-
-    fn into_par_iter(self) -> Self::Iter {
-        IterMut { slice: self }
-    }
-}
-
 /// Parallel iterator over immutable items in a slice
 #[derive(Debug)]
 pub struct Iter<'data, T: Sync> {
diff --git a/src/vec.rs b/src/vec.rs
index 686673b..8678ca5 100644
--- a/src/vec.rs
+++ b/src/vec.rs
@@ -8,12 +8,31 @@
 use crate::iter::plumbing::*;
 use crate::iter::*;
 use crate::math::simplify_range;
+use crate::slice::{Iter, IterMut};
 use std::iter;
 use std::mem;
 use std::ops::{Range, RangeBounds};
 use std::ptr;
 use std::slice;
 
+impl<'data, T: Sync + 'data> IntoParallelIterator for &'data Vec<T> {
+    type Item = &'data T;
+    type Iter = Iter<'data, T>;
+
+    fn into_par_iter(self) -> Self::Iter {
+        <&[T]>::into_par_iter(self)
+    }
+}
+
+impl<'data, T: Send + 'data> IntoParallelIterator for &'data mut Vec<T> {
+    type Item = &'data mut T;
+    type Iter = IterMut<'data, T>;
+
+    fn into_par_iter(self) -> Self::Iter {
+        <&mut [T]>::into_par_iter(self)
+    }
+}
+
 /// Parallel iterator that moves out of a vector.
 #[derive(Debug, Clone)]
 pub struct IntoIter<T: Send> {


Test patch:
diff --git a/tests/clones.rs b/tests/clones.rs
index fa93f8a..9add775 100644
--- a/tests/clones.rs
+++ b/tests/clones.rs
@@ -107,6 +107,12 @@ fn clone_vec() {
     check(v.into_par_iter());
 }
 
+#[test]
+fn clone_array() {
+    let a = [0i32; 100];
+    check(a.into_par_iter());
+}
+
 #[test]
 fn clone_adaptors() {
     let v: Vec<_> = (0..1000).map(Some).collect();
diff --git a/tests/debug.rs b/tests/debug.rs
index fb11110..3584ba0 100644
--- a/tests/debug.rs
+++ b/tests/debug.rs
@@ -130,6 +130,12 @@ fn debug_vec() {
     check(v.into_par_iter());
 }
 
+#[test]
+fn debug_array() {
+    let a = [0i32; 10];
+    check(a.into_par_iter());
+}
+
 #[test]
 fn debug_adaptors() {
     let v: Vec<_> = (0..10).collect();
diff --git a/tests/producer_split_at.rs b/tests/producer_split_at.rs
index 752bc3e..3a49059 100644
--- a/tests/producer_split_at.rs
+++ b/tests/producer_split_at.rs
@@ -108,6 +108,12 @@ fn check_len<I: ExactSizeIterator>(iter: &I, len: usize) {
 
 // **** Base Producers ****
 
+#[test]
+fn array() {
+    let a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    check(&a, || a);
+}
+
 #[test]
 fn empty() {
     let v = vec![42];