diff --git a/src/libcore/array.rs b/src/libcore/array.rs index c986914440de0..fafcc850c3f74 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -26,7 +26,7 @@ use convert::{AsRef, AsMut}; use default::Default; use fmt; use hash::{Hash, self}; -use iter::IntoIterator; +use iter::{FromIterator, IntoIterator, Iterator}; use marker::{Copy, Sized, Unsize}; use option::Option; use slice::{Iter, IterMut, SliceExt}; @@ -62,7 +62,7 @@ unsafe impl> FixedSizeArray for A { } } -// macro for implementing n-ary tuple functions and operations +// macro for implementing n-ary array functions and operations macro_rules! array_impls { ($($N:expr)+) => { $( @@ -188,8 +188,8 @@ array_impls! { 30 31 32 } -// The Default impls cannot be generated using the array_impls! macro because -// they require array literals. +// The following impls cannot be generated using the array_impls! macro because +// they require array expressions. macro_rules! array_impl_default { {$n:expr, $t:ident $($ts:ident)*} => { @@ -210,3 +210,30 @@ 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} + +macro_rules! array_impl_from_iterator { + {$n:expr, $i:ident $($is:ident)*} => { + impl FromIterator for [T; $n] { + fn from_iter>(iterator: I) -> Self { + let mut $i = iterator.into_iter(); + let a = [ + $i.next().expect("iterator too short"), + $($is.next().expect("iterator too short")),* + ]; + assert!($i.next().is_none(), "iterator too long"); + a + } + } + array_impl_from_iterator!{($n - 1), $($is)*} + }; + {$n:expr,} => { + impl FromIterator for [T; $n] { + fn from_iter>(iterator: I) -> Self { + assert!(iterator.into_iter().next().is_none(), "iterator too long"); + [] + } + } + }; +} + +array_impl_from_iterator!{32, i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i} diff --git a/src/libcoretest/array.rs b/src/libcoretest/array.rs index 6af031dee5845..5c26aba5a123d 100644 --- a/src/libcoretest/array.rs +++ b/src/libcoretest/array.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use core::array::FixedSizeArray; +use core::iter::{empty, Iterator, repeat}; #[test] fn fixed_size_array() { @@ -26,3 +27,29 @@ fn fixed_size_array() { assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_array).len(), 0); assert_eq!(FixedSizeArray::as_mut_slice(&mut empty_zero_sized).len(), 0); } + +#[test] +fn test_from_iter() { + assert_eq!((0..3).collect::<[u8; 3]>(), [0, 1, 2]); + assert_eq!((0..5).map(|x| x * x).collect::<[i32; 5]>(), [0, 1, 4, 9, 16]); + assert_eq!(repeat([0, 1, 2]).take(32).collect::<[[u64; 3]; 32]>(), [[0, 1, 2]; 32]); + assert_eq!(empty().collect::<[u8; 0]>(), []); +} + +#[test] +#[should_panic(expected = "iterator too short")] +fn test_from_iter_too_short() { + (0..2).collect::<[i32; 3]>(); +} + +#[test] +#[should_panic(expected = "iterator too long")] +fn test_from_iter_too_long() { + (0..3).collect::<[i32; 2]>(); +} + +#[test] +#[should_panic(expected = "iterator too long")] +fn test_from_iter_too_long_empty() { + repeat(0).collect::<[i32; 0]>(); +} diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index df12952fc324f..c5ec6304a8c48 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -167,6 +167,7 @@ mod prim_pointer { } /// /// - `Clone` (only if `T: Copy`) /// - `Debug` +/// - `FromIterator` /// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`) /// - `PartialEq`, `PartialOrd`, `Ord`, `Eq` /// - `Hash`