Skip to content

Commit be75eb3

Browse files
committed
Auto merge of #49000 - cuviper:array-intoiter, r=<try>
impl IntoIterator for arrays This allows an array to move its values out through iteration. This was attempted once before in #32871, but closed because the `IntoIter<T, [T; $N]>` type is not something we would want to stabilize. However, RFC 2000's const generics (#44580) are now on the horizon, so we can plan on changing this to `IntoIter<T, const N: usize>` before stabilization. Adding the `impl IntoIterator` now will allows folks to go ahead and iterate arrays in stable code. They just won't be able to name the `array::IntoIter` type or use its inherent `as_slice`/`as_mut_slice` methods until they've stabilized. Quite a few iterator examples were already using `.into_iter()` on arrays, getting auto-deref'ed to the slice iterator. These were easily fixed by calling `.iter()` instead, but it shows that this might cause a lot of breaking changes in the wild, and we'll need a crater run to evaluate this. Outside of examples, there was only one instance of in-tree code that had a problem. Fixes #25725. r? @alexcrichton
2 parents fab632f + 032f93b commit be75eb3

File tree

6 files changed

+371
-26
lines changed

6 files changed

+371
-26
lines changed

Diff for: src/libcore/array.rs

+188-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ use cmp::Ordering;
2424
use convert::TryFrom;
2525
use fmt;
2626
use hash::{Hash, self};
27-
use marker::Unsize;
27+
use iter::{FusedIterator, TrustedLen};
28+
use marker::{PhantomData, Unsize};
29+
use mem::{ManuallyDrop, self};
30+
use ptr;
2831
use slice::{Iter, IterMut};
2932

3033
/// Utility trait implemented only on arrays of fixed size
@@ -52,6 +55,7 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
5255
fn as_slice(&self) -> &[T] {
5356
self
5457
}
58+
5559
#[inline]
5660
fn as_mut_slice(&mut self) -> &mut [T] {
5761
self
@@ -210,6 +214,21 @@ macro_rules! array_impls {
210214
}
211215
}
212216

217+
#[unstable(feature = "array_into_iter", issue = "0")]
218+
impl<T> IntoIterator for [T; $N] {
219+
type Item = T;
220+
type IntoIter = IntoIter<T, Self>;
221+
222+
fn into_iter(self) -> Self::IntoIter {
223+
Self::IntoIter {
224+
array: ManuallyDrop::new(self),
225+
index: 0,
226+
index_back: $N,
227+
_marker: PhantomData,
228+
}
229+
}
230+
}
231+
213232
// NOTE: some less important impls are omitted to reduce code bloat
214233
__impl_slice_eq1! { [A; $N], [B; $N] }
215234
__impl_slice_eq2! { [A; $N], [B] }
@@ -285,3 +304,171 @@ macro_rules! array_impl_default {
285304
}
286305

287306
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}
307+
308+
309+
/// An iterator that moves out of an array.
310+
///
311+
/// This `struct` is created by the `into_iter` method on [arrays]
312+
/// (provided by the [`IntoIterator`] trait).
313+
///
314+
/// [arrays]: ../../std/primitive.array.html
315+
/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
316+
#[unstable(feature = "array_into_iter", issue = "0")]
317+
pub struct IntoIter<T, A: FixedSizeArray<T>> {
318+
// Invariants: index <= index_back <= array.len()
319+
// Only values in array[index..index_back] are alive at any given time.
320+
// Values from array[..index] and array[index_back..] are already moved/dropped.
321+
array: ManuallyDrop<A>,
322+
index: usize,
323+
index_back: usize,
324+
_marker: PhantomData<T>,
325+
}
326+
327+
impl<T, A: FixedSizeArray<T>> IntoIter<T, A> {
328+
/// Returns the remaining items of this iterator as a slice.
329+
///
330+
/// # Examples
331+
///
332+
/// ```
333+
/// #![feature(array_into_iter)]
334+
///
335+
/// # fn main() {
336+
/// let array = ['a', 'b', 'c'];
337+
/// let mut into_iter = array.into_iter();
338+
/// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
339+
/// let _ = into_iter.next().unwrap();
340+
/// assert_eq!(into_iter.as_slice(), &['b', 'c']);
341+
/// # }
342+
/// ```
343+
#[inline]
344+
#[unstable(feature = "array_into_iter", issue = "0")]
345+
pub fn as_slice(&self) -> &[T] {
346+
&self.array.as_slice()[self.index..self.index_back]
347+
}
348+
349+
/// Returns the remaining items of this iterator as a mutable slice.
350+
///
351+
/// # Examples
352+
///
353+
/// ```
354+
/// #![feature(array_into_iter)]
355+
///
356+
/// # fn main() {
357+
/// let array = ['a', 'b', 'c'];
358+
/// let mut into_iter = array.into_iter();
359+
/// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
360+
/// into_iter.as_mut_slice()[2] = 'z';
361+
/// assert_eq!(into_iter.next().unwrap(), 'a');
362+
/// assert_eq!(into_iter.next().unwrap(), 'b');
363+
/// assert_eq!(into_iter.next().unwrap(), 'z');
364+
/// # }
365+
/// ```
366+
#[inline]
367+
#[unstable(feature = "array_into_iter", issue = "0")]
368+
pub fn as_mut_slice(&mut self) -> &mut [T] {
369+
&mut self.array.as_mut_slice()[self.index..self.index_back]
370+
}
371+
}
372+
373+
#[unstable(feature = "array_into_iter", issue = "0")]
374+
impl<T, A: FixedSizeArray<T>> Drop for IntoIter<T, A> {
375+
#[inline]
376+
fn drop(&mut self) {
377+
// Drop values that are still alive.
378+
for p in self.as_mut_slice() {
379+
unsafe { ptr::drop_in_place(p); }
380+
}
381+
}
382+
}
383+
384+
#[unstable(feature = "array_into_iter", issue = "0")]
385+
impl<T: Clone, A: FixedSizeArray<T>> Clone for IntoIter<T, A> {
386+
fn clone(&self) -> Self {
387+
unsafe {
388+
let mut iter = Self {
389+
array: ManuallyDrop::new(mem::uninitialized()),
390+
index: 0,
391+
index_back: 0,
392+
_marker: PhantomData,
393+
};
394+
395+
// Clone values that are still alive.
396+
for (dst, src) in iter.array.as_mut_slice().iter_mut().zip(self.as_slice()) {
397+
ptr::write(dst, src.clone());
398+
iter.index_back += 1;
399+
}
400+
401+
iter
402+
}
403+
}
404+
}
405+
406+
#[unstable(feature = "array_into_iter", issue = "0")]
407+
impl<T: fmt::Debug, A: FixedSizeArray<T>> fmt::Debug for IntoIter<T, A> {
408+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409+
f.debug_tuple("IntoIter")
410+
.field(&self.as_slice())
411+
.finish()
412+
}
413+
}
414+
415+
#[unstable(feature = "array_into_iter", issue = "0")]
416+
impl<T, A: FixedSizeArray<T>> Iterator for IntoIter<T, A> {
417+
type Item = T;
418+
419+
#[inline]
420+
fn next(&mut self) -> Option<T> {
421+
if self.index < self.index_back {
422+
let p = &self.array.as_slice()[self.index];
423+
self.index += 1;
424+
unsafe { Some(ptr::read(p)) }
425+
} else {
426+
None
427+
}
428+
}
429+
430+
#[inline]
431+
fn size_hint(&self) -> (usize, Option<usize>) {
432+
let len = self.len();
433+
(len, Some(len))
434+
}
435+
436+
#[inline]
437+
fn count(self) -> usize {
438+
self.len()
439+
}
440+
}
441+
442+
#[unstable(feature = "array_into_iter", issue = "0")]
443+
impl<T, A: FixedSizeArray<T>> DoubleEndedIterator for IntoIter<T, A> {
444+
#[inline]
445+
fn next_back(&mut self) -> Option<T> {
446+
if self.index < self.index_back {
447+
self.index_back -= 1;
448+
let p = &self.array.as_slice()[self.index_back];
449+
unsafe { Some(ptr::read(p)) }
450+
} else {
451+
None
452+
}
453+
}
454+
}
455+
456+
#[unstable(feature = "array_into_iter", issue = "0")]
457+
impl<T, A: FixedSizeArray<T>> ExactSizeIterator for IntoIter<T, A> {
458+
#[inline]
459+
fn len(&self) -> usize {
460+
self.index_back - self.index
461+
}
462+
463+
#[inline]
464+
fn is_empty(&self) -> bool {
465+
self.index_back == self.index
466+
}
467+
}
468+
469+
#[unstable(feature = "array_into_iter", issue = "0")]
470+
impl<T, A: FixedSizeArray<T>> FusedIterator for IntoIter<T, A> {}
471+
472+
// #[unstable(feature = "trusted_len", issue = "37572")]
473+
#[unstable(feature = "array_into_iter", issue = "0")]
474+
unsafe impl<T, A: FixedSizeArray<T>> TrustedLen for IntoIter<T, A> {}

Diff for: src/libcore/iter/iterator.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ pub trait Iterator {
285285
/// ```
286286
/// #![feature(iterator_step_by)]
287287
/// let a = [0, 1, 2, 3, 4, 5];
288-
/// let mut iter = a.into_iter().step_by(2);
288+
/// let mut iter = a.iter().step_by(2);
289289
///
290290
/// assert_eq!(iter.next(), Some(&0));
291291
/// assert_eq!(iter.next(), Some(&2));
@@ -461,7 +461,7 @@ pub trait Iterator {
461461
/// ```
462462
/// let a = [1, 2, 3];
463463
///
464-
/// let mut iter = a.into_iter().map(|x| 2 * x);
464+
/// let mut iter = a.iter().map(|x| 2 * x);
465465
///
466466
/// assert_eq!(iter.next(), Some(2));
467467
/// assert_eq!(iter.next(), Some(4));
@@ -550,7 +550,7 @@ pub trait Iterator {
550550
/// ```
551551
/// let a = [0i32, 1, 2];
552552
///
553-
/// let mut iter = a.into_iter().filter(|x| x.is_positive());
553+
/// let mut iter = a.iter().filter(|x| x.is_positive());
554554
///
555555
/// assert_eq!(iter.next(), Some(&1));
556556
/// assert_eq!(iter.next(), Some(&2));
@@ -564,7 +564,7 @@ pub trait Iterator {
564564
/// ```
565565
/// let a = [0, 1, 2];
566566
///
567-
/// let mut iter = a.into_iter().filter(|x| **x > 1); // need two *s!
567+
/// let mut iter = a.iter().filter(|x| **x > 1); // need two *s!
568568
///
569569
/// assert_eq!(iter.next(), Some(&2));
570570
/// assert_eq!(iter.next(), None);
@@ -576,7 +576,7 @@ pub trait Iterator {
576576
/// ```
577577
/// let a = [0, 1, 2];
578578
///
579-
/// let mut iter = a.into_iter().filter(|&x| *x > 1); // both & and *
579+
/// let mut iter = a.iter().filter(|&x| *x > 1); // both & and *
580580
///
581581
/// assert_eq!(iter.next(), Some(&2));
582582
/// assert_eq!(iter.next(), None);
@@ -587,7 +587,7 @@ pub trait Iterator {
587587
/// ```
588588
/// let a = [0, 1, 2];
589589
///
590-
/// let mut iter = a.into_iter().filter(|&&x| x > 1); // two &s
590+
/// let mut iter = a.iter().filter(|&&x| x > 1); // two &s
591591
///
592592
/// assert_eq!(iter.next(), Some(&2));
593593
/// assert_eq!(iter.next(), None);
@@ -767,7 +767,7 @@ pub trait Iterator {
767767
/// ```
768768
/// let a = [-1i32, 0, 1];
769769
///
770-
/// let mut iter = a.into_iter().skip_while(|x| x.is_negative());
770+
/// let mut iter = a.iter().skip_while(|x| x.is_negative());
771771
///
772772
/// assert_eq!(iter.next(), Some(&0));
773773
/// assert_eq!(iter.next(), Some(&1));
@@ -781,7 +781,7 @@ pub trait Iterator {
781781
/// ```
782782
/// let a = [-1, 0, 1];
783783
///
784-
/// let mut iter = a.into_iter().skip_while(|x| **x < 0); // need two *s!
784+
/// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s!
785785
///
786786
/// assert_eq!(iter.next(), Some(&0));
787787
/// assert_eq!(iter.next(), Some(&1));
@@ -793,7 +793,7 @@ pub trait Iterator {
793793
/// ```
794794
/// let a = [-1, 0, 1, -2];
795795
///
796-
/// let mut iter = a.into_iter().skip_while(|x| **x < 0);
796+
/// let mut iter = a.iter().skip_while(|x| **x < 0);
797797
///
798798
/// assert_eq!(iter.next(), Some(&0));
799799
/// assert_eq!(iter.next(), Some(&1));
@@ -828,7 +828,7 @@ pub trait Iterator {
828828
/// ```
829829
/// let a = [-1i32, 0, 1];
830830
///
831-
/// let mut iter = a.into_iter().take_while(|x| x.is_negative());
831+
/// let mut iter = a.iter().take_while(|x| x.is_negative());
832832
///
833833
/// assert_eq!(iter.next(), Some(&-1));
834834
/// assert_eq!(iter.next(), None);
@@ -841,7 +841,7 @@ pub trait Iterator {
841841
/// ```
842842
/// let a = [-1, 0, 1];
843843
///
844-
/// let mut iter = a.into_iter().take_while(|x| **x < 0); // need two *s!
844+
/// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s!
845845
///
846846
/// assert_eq!(iter.next(), Some(&-1));
847847
/// assert_eq!(iter.next(), None);
@@ -852,7 +852,7 @@ pub trait Iterator {
852852
/// ```
853853
/// let a = [-1, 0, 1, -2];
854854
///
855-
/// let mut iter = a.into_iter().take_while(|x| **x < 0);
855+
/// let mut iter = a.iter().take_while(|x| **x < 0);
856856
///
857857
/// assert_eq!(iter.next(), Some(&-1));
858858
///
@@ -867,7 +867,7 @@ pub trait Iterator {
867867
///
868868
/// ```
869869
/// let a = [1, 2, 3, 4];
870-
/// let mut iter = a.into_iter();
870+
/// let mut iter = a.iter();
871871
///
872872
/// let result: Vec<i32> = iter.by_ref()
873873
/// .take_while(|n| **n != 3)
@@ -1229,7 +1229,7 @@ pub trait Iterator {
12291229
/// ```
12301230
/// let a = [1, 2, 3];
12311231
///
1232-
/// let iter = a.into_iter();
1232+
/// let iter = a.iter();
12331233
///
12341234
/// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i );
12351235
///
@@ -1242,7 +1242,7 @@ pub trait Iterator {
12421242
/// // let's try that again
12431243
/// let a = [1, 2, 3];
12441244
///
1245-
/// let mut iter = a.into_iter();
1245+
/// let mut iter = a.iter();
12461246
///
12471247
/// // instead, we add in a .by_ref()
12481248
/// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i );
@@ -1386,7 +1386,7 @@ pub trait Iterator {
13861386
/// let a = [1, 2, 3];
13871387
///
13881388
/// let (even, odd): (Vec<i32>, Vec<i32>) = a
1389-
/// .into_iter()
1389+
/// .iter()
13901390
/// .partition(|&n| n % 2 == 0);
13911391
///
13921392
/// assert_eq!(even, vec![2]);

0 commit comments

Comments
 (0)