Skip to content

Commit a302155

Browse files
authoredOct 25, 2019
Rollup merge of rust-lang#62959 - LukasKalbertodt:array-value-iter, r=scottmcm
Add by-value iterator for arrays This adds an iterator that can iterate over arrays by value, yielding all elements by value. However, **this PR does _not_ add a corresponding `IntoIterator` impl for arrays**. The `IntoIterator` impl needs some discussion about backwards-compatibility that should take place in a separate PR. With this patch, this code should work (but there is currently still a bug): ```rust #![feature(array_value_iter)] use std::array::IntoIter; let arr = [1, 2, 3]; for x in IntoIter::new(arr) { println!("{}", x); } ``` **TODO**: - [x] Get initial feedback - [x] Add tests - [x] Figure out why stage1 produces weird bugs ([comment](rust-lang#62959 (comment))) - [x] Add UI tests as mentioned [here](rust-lang#62959 (comment)) (will do that soon-ish) - [x] Fix [this new bug](rust-lang#62959 (comment)) **Notes for reviewers** - Is the use of `MaybeUninit` correct here? I think it has to be used due to the `Clone` impl which has to fill the dead array elements with something, but cannot fill it with a correct instance. - Are the unit tests sufficient? CC rust-lang#25725
2 parents d54111a + c36b9dd commit a302155

File tree

7 files changed

+696
-1
lines changed

7 files changed

+696
-1
lines changed
 

‎src/libcore/array/iter.rs

+266
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
//! Defines the `IntoIter` owned iterator for arrays.
2+
3+
use crate::{
4+
fmt,
5+
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
6+
mem::{self, MaybeUninit},
7+
ops::Range,
8+
ptr,
9+
};
10+
use super::LengthAtMost32;
11+
12+
13+
/// A by-value [array] iterator.
14+
///
15+
/// [array]: ../../std/primitive.array.html
16+
#[unstable(feature = "array_value_iter", issue = "0")]
17+
pub struct IntoIter<T, const N: usize>
18+
where
19+
[T; N]: LengthAtMost32,
20+
{
21+
/// This is the array we are iterating over.
22+
///
23+
/// Elements with index `i` where `alive.start <= i < alive.end` have not
24+
/// been yielded yet and are valid array entries. Elements with indices `i
25+
/// < alive.start` or `i >= alive.end` have been yielded already and must
26+
/// not be accessed anymore! Those dead elements might even be in a
27+
/// completely uninitialized state!
28+
///
29+
/// So the invariants are:
30+
/// - `data[alive]` is alive (i.e. contains valid elements)
31+
/// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
32+
/// elements were already read and must not be touched anymore!)
33+
data: [MaybeUninit<T>; N],
34+
35+
/// The elements in `data` that have not been yielded yet.
36+
///
37+
/// Invariants:
38+
/// - `alive.start <= alive.end`
39+
/// - `alive.end <= N`
40+
alive: Range<usize>,
41+
}
42+
43+
impl<T, const N: usize> IntoIter<T, {N}>
44+
where
45+
[T; N]: LengthAtMost32,
46+
{
47+
/// Creates a new iterator over the given `array`.
48+
///
49+
/// *Note*: this method might never get stabilized and/or removed in the
50+
/// future as there will likely be another, preferred way of obtaining this
51+
/// iterator (either via `IntoIterator` for arrays or via another way).
52+
#[unstable(feature = "array_value_iter", issue = "0")]
53+
pub fn new(array: [T; N]) -> Self {
54+
// The transmute here is actually safe. The docs of `MaybeUninit`
55+
// promise:
56+
//
57+
// > `MaybeUninit<T>` is guaranteed to have the same size and alignment
58+
// > as `T`.
59+
//
60+
// The docs even show a transmute from an array of `MaybeUninit<T>` to
61+
// an array of `T`.
62+
//
63+
// With that, this initialization satisfies the invariants.
64+
65+
// FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
66+
// works with const generics:
67+
// `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
68+
//
69+
// Until then, we do it manually here. We first create a bitwise copy
70+
// but cast the pointer so that it is treated as a different type. Then
71+
// we forget `array` so that it is not dropped.
72+
let data = unsafe {
73+
let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
74+
mem::forget(array);
75+
data
76+
};
77+
78+
Self {
79+
data,
80+
alive: 0..N,
81+
}
82+
}
83+
84+
/// Returns an immutable slice of all elements that have not been yielded
85+
/// yet.
86+
fn as_slice(&self) -> &[T] {
87+
// This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
88+
// the size and alignment of `T`. Furthermore, we know that all
89+
// elements within `alive` are properly initialized.
90+
let slice = &self.data[self.alive.clone()];
91+
unsafe {
92+
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
93+
}
94+
}
95+
}
96+
97+
98+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
99+
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
100+
where
101+
[T; N]: LengthAtMost32,
102+
{
103+
type Item = T;
104+
fn next(&mut self) -> Option<Self::Item> {
105+
if self.alive.start == self.alive.end {
106+
return None;
107+
}
108+
109+
// Bump start index.
110+
//
111+
// From the check above we know that `alive.start != alive.end`.
112+
// Combine this with the invariant `alive.start <= alive.end`, we know
113+
// that `alive.start < alive.end`. Increasing `alive.start` by 1
114+
// maintains the invariant regarding `alive`. However, due to this
115+
// change, for a short time, the alive zone is not `data[alive]`
116+
// anymore, but `data[idx..alive.end]`.
117+
let idx = self.alive.start;
118+
self.alive.start += 1;
119+
120+
// Read the element from the array. This is safe: `idx` is an index
121+
// into the "alive" region of the array. Reading this element means
122+
// that `data[idx]` is regarded as dead now (i.e. do not touch). As
123+
// `idx` was the start of the alive-zone, the alive zone is now
124+
// `data[alive]` again, restoring all invariants.
125+
let out = unsafe { self.data.get_unchecked(idx).read() };
126+
127+
Some(out)
128+
}
129+
130+
fn size_hint(&self) -> (usize, Option<usize>) {
131+
let len = self.len();
132+
(len, Some(len))
133+
}
134+
135+
fn count(self) -> usize {
136+
self.len()
137+
}
138+
139+
fn last(mut self) -> Option<Self::Item> {
140+
self.next_back()
141+
}
142+
}
143+
144+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
145+
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
146+
where
147+
[T; N]: LengthAtMost32,
148+
{
149+
fn next_back(&mut self) -> Option<Self::Item> {
150+
if self.alive.start == self.alive.end {
151+
return None;
152+
}
153+
154+
// Decrease end index.
155+
//
156+
// From the check above we know that `alive.start != alive.end`.
157+
// Combine this with the invariant `alive.start <= alive.end`, we know
158+
// that `alive.start < alive.end`. As `alive.start` cannot be negative,
159+
// `alive.end` is at least 1, meaning that we can safely decrement it
160+
// by one. This also maintains the invariant `alive.start <=
161+
// alive.end`. However, due to this change, for a short time, the alive
162+
// zone is not `data[alive]` anymore, but `data[alive.start..alive.end
163+
// + 1]`.
164+
self.alive.end -= 1;
165+
166+
// Read the element from the array. This is safe: `alive.end` is an
167+
// index into the "alive" region of the array. Compare the previous
168+
// comment that states that the alive region is
169+
// `data[alive.start..alive.end + 1]`. Reading this element means that
170+
// `data[alive.end]` is regarded as dead now (i.e. do not touch). As
171+
// `alive.end` was the end of the alive-zone, the alive zone is now
172+
// `data[alive]` again, restoring all invariants.
173+
let out = unsafe { self.data.get_unchecked(self.alive.end).read() };
174+
175+
Some(out)
176+
}
177+
}
178+
179+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
180+
impl<T, const N: usize> Drop for IntoIter<T, {N}>
181+
where
182+
[T; N]: LengthAtMost32,
183+
{
184+
fn drop(&mut self) {
185+
// We simply drop each element via `for_each`. This should not incur
186+
// any significant runtime overhead and avoids adding another `unsafe`
187+
// block.
188+
self.by_ref().for_each(drop);
189+
}
190+
}
191+
192+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
193+
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
194+
where
195+
[T; N]: LengthAtMost32,
196+
{
197+
fn len(&self) -> usize {
198+
// Will never underflow due to the invariant `alive.start <=
199+
// alive.end`.
200+
self.alive.end - self.alive.start
201+
}
202+
fn is_empty(&self) -> bool {
203+
self.alive.is_empty()
204+
}
205+
}
206+
207+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
208+
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
209+
where
210+
[T; N]: LengthAtMost32,
211+
{}
212+
213+
// The iterator indeed reports the correct length. The number of "alive"
214+
// elements (that will still be yielded) is the length of the range `alive`.
215+
// This range is decremented in length in either `next` or `next_back`. It is
216+
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
217+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
218+
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
219+
where
220+
[T; N]: LengthAtMost32,
221+
{}
222+
223+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
224+
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
225+
where
226+
[T; N]: LengthAtMost32,
227+
{
228+
fn clone(&self) -> Self {
229+
unsafe {
230+
// This creates a new uninitialized array. Note that the `assume_init`
231+
// refers to the array, not the individual elements. And it is Ok if
232+
// the array is in an uninitialized state as all elements may be
233+
// uninitialized (all bit patterns are valid). Compare the
234+
// `MaybeUninit` docs for more information.
235+
let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
236+
237+
// Clone all alive elements.
238+
for idx in self.alive.clone() {
239+
// The element at `idx` in the old array is alive, so we can
240+
// safely call `get_ref()`. We then clone it, and write the
241+
// clone into the new array.
242+
let clone = self.data.get_unchecked(idx).get_ref().clone();
243+
new_data.get_unchecked_mut(idx).write(clone);
244+
}
245+
246+
Self {
247+
data: new_data,
248+
alive: self.alive.clone(),
249+
}
250+
}
251+
}
252+
}
253+
254+
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
255+
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
256+
where
257+
[T; N]: LengthAtMost32,
258+
{
259+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260+
// Only print the elements that were not yielded yet: we cannot
261+
// access the yielded elements anymore.
262+
f.debug_tuple("IntoIter")
263+
.field(&self.as_slice())
264+
.finish()
265+
}
266+
}

‎src/libcore/array.rs ‎src/libcore/array/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ use crate::hash::{Hash, self};
1414
use crate::marker::Unsize;
1515
use crate::slice::{Iter, IterMut};
1616

17+
#[cfg(not(bootstrap))]
18+
mod iter;
19+
20+
#[cfg(not(bootstrap))]
21+
#[unstable(feature = "array_value_iter", issue = "0")]
22+
pub use iter::IntoIter;
23+
1724
/// Utility trait implemented only on arrays of fixed size
1825
///
1926
/// This trait can be used to implement other traits on fixed-size arrays

‎src/libcore/tests/array.rs

+206-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::array::FixedSizeArray;
1+
use core::array::{FixedSizeArray, IntoIter};
22
use core::convert::TryFrom;
33

44
#[test]
@@ -40,3 +40,208 @@ fn array_try_from() {
4040
30 31 32
4141
}
4242
}
43+
44+
45+
#[test]
46+
fn iterator_collect() {
47+
let arr = [0, 1, 2, 5, 9];
48+
let v: Vec<_> = IntoIter::new(arr.clone()).collect();
49+
assert_eq!(&arr[..], &v[..]);
50+
}
51+
52+
#[test]
53+
fn iterator_rev_collect() {
54+
let arr = [0, 1, 2, 5, 9];
55+
let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
56+
assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
57+
}
58+
59+
#[test]
60+
fn iterator_nth() {
61+
let v = [0, 1, 2, 3, 4];
62+
for i in 0..v.len() {
63+
assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
64+
}
65+
assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);
66+
67+
let mut iter = IntoIter::new(v);
68+
assert_eq!(iter.nth(2).unwrap(), v[2]);
69+
assert_eq!(iter.nth(1).unwrap(), v[4]);
70+
}
71+
72+
#[test]
73+
fn iterator_last() {
74+
let v = [0, 1, 2, 3, 4];
75+
assert_eq!(IntoIter::new(v).last().unwrap(), 4);
76+
assert_eq!(IntoIter::new([0]).last().unwrap(), 0);
77+
78+
let mut it = IntoIter::new([0, 9, 2, 4]);
79+
assert_eq!(it.next_back(), Some(4));
80+
assert_eq!(it.last(), Some(2));
81+
}
82+
83+
#[test]
84+
fn iterator_clone() {
85+
let mut it = IntoIter::new([0, 2, 4, 6, 8]);
86+
assert_eq!(it.next(), Some(0));
87+
assert_eq!(it.next_back(), Some(8));
88+
let mut clone = it.clone();
89+
assert_eq!(it.next_back(), Some(6));
90+
assert_eq!(clone.next_back(), Some(6));
91+
assert_eq!(it.next_back(), Some(4));
92+
assert_eq!(clone.next_back(), Some(4));
93+
assert_eq!(it.next(), Some(2));
94+
assert_eq!(clone.next(), Some(2));
95+
}
96+
97+
#[test]
98+
fn iterator_fused() {
99+
let mut it = IntoIter::new([0, 9, 2]);
100+
assert_eq!(it.next(), Some(0));
101+
assert_eq!(it.next(), Some(9));
102+
assert_eq!(it.next(), Some(2));
103+
assert_eq!(it.next(), None);
104+
assert_eq!(it.next(), None);
105+
assert_eq!(it.next(), None);
106+
assert_eq!(it.next(), None);
107+
assert_eq!(it.next(), None);
108+
}
109+
110+
#[test]
111+
fn iterator_len() {
112+
let mut it = IntoIter::new([0, 1, 2, 5, 9]);
113+
assert_eq!(it.size_hint(), (5, Some(5)));
114+
assert_eq!(it.len(), 5);
115+
assert_eq!(it.is_empty(), false);
116+
117+
assert_eq!(it.next(), Some(0));
118+
assert_eq!(it.size_hint(), (4, Some(4)));
119+
assert_eq!(it.len(), 4);
120+
assert_eq!(it.is_empty(), false);
121+
122+
assert_eq!(it.next_back(), Some(9));
123+
assert_eq!(it.size_hint(), (3, Some(3)));
124+
assert_eq!(it.len(), 3);
125+
assert_eq!(it.is_empty(), false);
126+
127+
// Empty
128+
let it = IntoIter::new([] as [String; 0]);
129+
assert_eq!(it.size_hint(), (0, Some(0)));
130+
assert_eq!(it.len(), 0);
131+
assert_eq!(it.is_empty(), true);
132+
}
133+
134+
#[test]
135+
fn iterator_count() {
136+
let v = [0, 1, 2, 3, 4];
137+
assert_eq!(IntoIter::new(v.clone()).count(), 5);
138+
139+
let mut iter2 = IntoIter::new(v);
140+
iter2.next();
141+
iter2.next();
142+
assert_eq!(iter2.count(), 3);
143+
}
144+
145+
#[test]
146+
fn iterator_flat_map() {
147+
assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
148+
}
149+
150+
#[test]
151+
fn iterator_debug() {
152+
let arr = [0, 1, 2, 5, 9];
153+
assert_eq!(
154+
format!("{:?}", IntoIter::new(arr)),
155+
"IntoIter([0, 1, 2, 5, 9])",
156+
);
157+
}
158+
159+
#[test]
160+
fn iterator_drops() {
161+
use core::cell::Cell;
162+
163+
// This test makes sure the correct number of elements are dropped. The `R`
164+
// type is just a reference to a `Cell` that is incremented when an `R` is
165+
// dropped.
166+
167+
#[derive(Clone)]
168+
struct Foo<'a>(&'a Cell<usize>);
169+
170+
impl Drop for Foo<'_> {
171+
fn drop(&mut self) {
172+
self.0.set(self.0.get() + 1);
173+
}
174+
}
175+
176+
fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
177+
// This is somewhat verbose because `Foo` does not implement `Copy`
178+
// since it implements `Drop`. Consequently, we cannot write
179+
// `[Foo(i); 5]`.
180+
[Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
181+
}
182+
183+
// Simple: drop new iterator.
184+
let i = Cell::new(0);
185+
{
186+
IntoIter::new(five(&i));
187+
}
188+
assert_eq!(i.get(), 5);
189+
190+
// Call `next()` once.
191+
let i = Cell::new(0);
192+
{
193+
let mut iter = IntoIter::new(five(&i));
194+
let _x = iter.next();
195+
assert_eq!(i.get(), 0);
196+
assert_eq!(iter.count(), 4);
197+
assert_eq!(i.get(), 4);
198+
}
199+
assert_eq!(i.get(), 5);
200+
201+
// Check `clone` and calling `next`/`next_back`.
202+
let i = Cell::new(0);
203+
{
204+
let mut iter = IntoIter::new(five(&i));
205+
iter.next();
206+
assert_eq!(i.get(), 1);
207+
iter.next_back();
208+
assert_eq!(i.get(), 2);
209+
210+
let mut clone = iter.clone();
211+
assert_eq!(i.get(), 2);
212+
213+
iter.next();
214+
assert_eq!(i.get(), 3);
215+
216+
clone.next();
217+
assert_eq!(i.get(), 4);
218+
219+
assert_eq!(clone.count(), 2);
220+
assert_eq!(i.get(), 6);
221+
}
222+
assert_eq!(i.get(), 8);
223+
224+
// Check via `nth`.
225+
let i = Cell::new(0);
226+
{
227+
let mut iter = IntoIter::new(five(&i));
228+
let _x = iter.nth(2);
229+
assert_eq!(i.get(), 2);
230+
let _y = iter.last();
231+
assert_eq!(i.get(), 3);
232+
}
233+
assert_eq!(i.get(), 5);
234+
235+
// Check every element.
236+
let i = Cell::new(0);
237+
for (index, _x) in IntoIter::new(five(&i)).enumerate() {
238+
assert_eq!(i.get(), index);
239+
}
240+
assert_eq!(i.get(), 5);
241+
242+
let i = Cell::new(0);
243+
for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
244+
assert_eq!(i.get(), index);
245+
}
246+
assert_eq!(i.get(), 5);
247+
}

‎src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(slice_partition_dedup)]
3232
#![feature(int_error_matching)]
3333
#![feature(const_fn)]
34+
#![feature(array_value_iter)]
3435
#![feature(iter_partition_in_place)]
3536
#![feature(iter_is_partitioned)]
3637
#![feature(iter_order_by)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// check-pass
2+
3+
#![feature(array_value_iter)]
4+
#![feature(trusted_len)]
5+
6+
use std::{
7+
array::IntoIter,
8+
fmt::Debug,
9+
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
10+
};
11+
12+
pub fn yes_iterator() -> impl Iterator<Item = i32> {
13+
IntoIter::new([0i32; 32])
14+
}
15+
16+
pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
17+
IntoIter::new([0i32; 32])
18+
}
19+
20+
pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
21+
IntoIter::new([0i32; 32])
22+
}
23+
24+
pub fn yes_fused_iterator() -> impl FusedIterator {
25+
IntoIter::new([0i32; 32])
26+
}
27+
28+
pub fn yes_trusted_len() -> impl TrustedLen {
29+
IntoIter::new([0i32; 32])
30+
}
31+
32+
pub fn yes_clone() -> impl Clone {
33+
IntoIter::new([0i32; 32])
34+
}
35+
36+
pub fn yes_debug() -> impl Debug {
37+
IntoIter::new([0i32; 32])
38+
}
39+
40+
41+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#![feature(array_value_iter)]
2+
#![feature(trusted_len)]
3+
4+
use std::{
5+
array::IntoIter,
6+
fmt::Debug,
7+
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
8+
};
9+
10+
pub fn no_iterator() -> impl Iterator<Item = i32> {
11+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
12+
IntoIter::new([0i32; 33])
13+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
14+
}
15+
16+
pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
17+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
18+
IntoIter::new([0i32; 33])
19+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
20+
}
21+
22+
pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
23+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
24+
IntoIter::new([0i32; 33])
25+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
26+
}
27+
28+
pub fn no_fused_iterator() -> impl FusedIterator {
29+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
30+
IntoIter::new([0i32; 33])
31+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
32+
}
33+
34+
pub fn no_trusted_len() -> impl TrustedLen {
35+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
36+
IntoIter::new([0i32; 33])
37+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
38+
}
39+
40+
pub fn no_clone() -> impl Clone {
41+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
42+
IntoIter::new([0i32; 33])
43+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
44+
}
45+
46+
pub fn no_debug() -> impl Debug {
47+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
48+
IntoIter::new([0i32; 33])
49+
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
50+
}
51+
52+
53+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
2+
--> $DIR/into-iter-no-impls-length-33.rs:12:5
3+
|
4+
LL | IntoIter::new([0i32; 33])
5+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
6+
|
7+
= note: required by `std::array::IntoIter::<T, N>::new`
8+
9+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
10+
--> $DIR/into-iter-no-impls-length-33.rs:10:25
11+
|
12+
LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
14+
|
15+
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
16+
= note: the return type of a function must have a statically known size
17+
18+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
19+
--> $DIR/into-iter-no-impls-length-33.rs:18:5
20+
|
21+
LL | IntoIter::new([0i32; 33])
22+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
23+
|
24+
= note: required by `std::array::IntoIter::<T, N>::new`
25+
26+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
27+
--> $DIR/into-iter-no-impls-length-33.rs:16:38
28+
|
29+
LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
31+
|
32+
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
33+
= note: the return type of a function must have a statically known size
34+
35+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
36+
--> $DIR/into-iter-no-impls-length-33.rs:24:5
37+
|
38+
LL | IntoIter::new([0i32; 33])
39+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
40+
|
41+
= note: required by `std::array::IntoIter::<T, N>::new`
42+
43+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
44+
--> $DIR/into-iter-no-impls-length-33.rs:22:36
45+
|
46+
LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
47+
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
48+
|
49+
= note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
50+
= note: the return type of a function must have a statically known size
51+
52+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
53+
--> $DIR/into-iter-no-impls-length-33.rs:30:5
54+
|
55+
LL | IntoIter::new([0i32; 33])
56+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
57+
|
58+
= note: required by `std::array::IntoIter::<T, N>::new`
59+
60+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
61+
--> $DIR/into-iter-no-impls-length-33.rs:28:31
62+
|
63+
LL | pub fn no_fused_iterator() -> impl FusedIterator {
64+
| ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
65+
|
66+
= note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
67+
= note: the return type of a function must have a statically known size
68+
69+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
70+
--> $DIR/into-iter-no-impls-length-33.rs:36:5
71+
|
72+
LL | IntoIter::new([0i32; 33])
73+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
74+
|
75+
= note: required by `std::array::IntoIter::<T, N>::new`
76+
77+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
78+
--> $DIR/into-iter-no-impls-length-33.rs:34:28
79+
|
80+
LL | pub fn no_trusted_len() -> impl TrustedLen {
81+
| ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
82+
|
83+
= note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
84+
= note: the return type of a function must have a statically known size
85+
86+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
87+
--> $DIR/into-iter-no-impls-length-33.rs:42:5
88+
|
89+
LL | IntoIter::new([0i32; 33])
90+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
91+
|
92+
= note: required by `std::array::IntoIter::<T, N>::new`
93+
94+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
95+
--> $DIR/into-iter-no-impls-length-33.rs:40:22
96+
|
97+
LL | pub fn no_clone() -> impl Clone {
98+
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
99+
|
100+
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
101+
= note: the return type of a function must have a statically known size
102+
103+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
104+
--> $DIR/into-iter-no-impls-length-33.rs:48:5
105+
|
106+
LL | IntoIter::new([0i32; 33])
107+
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
108+
|
109+
= note: required by `std::array::IntoIter::<T, N>::new`
110+
111+
error[E0277]: arrays only have std trait implementations for lengths 0..=32
112+
--> $DIR/into-iter-no-impls-length-33.rs:46:22
113+
|
114+
LL | pub fn no_debug() -> impl Debug {
115+
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
116+
|
117+
= note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
118+
= note: the return type of a function must have a statically known size
119+
120+
error: aborting due to 14 previous errors
121+
122+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)
Please sign in to comment.