Skip to content

Commit 8842949

Browse files
Implement for
Co-authored-by: Mark Rousskov <mark.simulacrum@gmail.com>
1 parent 057ed8b commit 8842949

10 files changed

Lines changed: 180 additions & 136 deletions

library/alloc/src/boxed.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ mod iter;
218218
/// [`ThinBox`] implementation.
219219
mod thin;
220220

221+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
222+
pub use iter::BoxedArrayIntoIter;
221223
#[unstable(feature = "thin_box", issue = "92791")]
222224
pub use thin::ThinBox;
223225

library/alloc/src/boxed/iter.rs

Lines changed: 155 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
use core::async_iter::AsyncIterator;
2-
use core::iter::FusedIterator;
2+
use core::iter::{FusedIterator, TrustedLen};
3+
use core::num::NonZero;
34
use core::pin::Pin;
45
use core::slice;
56
use core::task::{Context, Poll};
67

7-
use crate::alloc::Allocator;
8+
use crate::alloc::{Allocator, Global};
89
#[cfg(not(no_global_oom_handling))]
910
use crate::borrow::Cow;
1011
use crate::boxed::Box;
1112
#[cfg(not(no_global_oom_handling))]
1213
use crate::string::String;
13-
use crate::vec;
1414
#[cfg(not(no_global_oom_handling))]
1515
use crate::vec::Vec;
16+
use crate::{fmt, vec};
1617

1718
#[stable(feature = "rust1", since = "1.0.0")]
1819
impl<I: Iterator + ?Sized, A: Allocator> Iterator for Box<I, A> {
@@ -192,3 +193,154 @@ impl<'a> FromIterator<Cow<'a, str>> for Box<str> {
192193
String::from_iter(iter).into_boxed_str()
193194
}
194195
}
196+
197+
/// This implementation is required to make sure that the `Box<[I; N]>: IntoIterator`
198+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
199+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
200+
impl<I, const N: usize, A: Allocator> !Iterator for Box<[I; N], A> {}
201+
202+
/// This implementation is required to make sure that the `&Box<[I; N]>: IntoIterator`
203+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
204+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
205+
impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a Box<[I; N], A> {}
206+
207+
/// This implementation is required to make sure that the `&mut Box<[I; N]>: IntoIterator`
208+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
209+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
210+
impl<'a, const N: usize, I, A: Allocator> !Iterator for &'a mut Box<[I; N], A> {}
211+
212+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
213+
impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a Box<[T; N], A> {
214+
type IntoIter = slice::Iter<'a, T>;
215+
type Item = &'a T;
216+
fn into_iter(self) -> slice::Iter<'a, T> {
217+
self.iter()
218+
}
219+
}
220+
221+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
222+
impl<'a, T, const N: usize, A: Allocator> IntoIterator for &'a mut Box<[T; N], A> {
223+
type IntoIter = slice::IterMut<'a, T>;
224+
type Item = &'a mut T;
225+
fn into_iter(self) -> slice::IterMut<'a, T> {
226+
self.iter_mut()
227+
}
228+
}
229+
230+
/// A by-value `Box<[T; N]>` iterator.
231+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
232+
#[rustc_insignificant_dtor]
233+
pub struct BoxedArrayIntoIter<T, const N: usize, A: Allocator = Global> {
234+
// FIXME: make a more efficient implementation (without the need to store capacity)
235+
inner: vec::IntoIter<T, A>,
236+
}
237+
238+
impl<T, const N: usize, A: Allocator> BoxedArrayIntoIter<T, N, A> {
239+
/// Returns an immutable slice of all elements that have not been yielded
240+
/// yet.
241+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
242+
pub fn as_slice(&self) -> &[T] {
243+
self.inner.as_slice()
244+
}
245+
246+
/// Returns a mutable slice of all elements that have not been yielded yet.
247+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
248+
pub fn as_mut_slice(&mut self) -> &mut [T] {
249+
self.inner.as_mut_slice()
250+
}
251+
}
252+
253+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
254+
impl<T, const N: usize, A: Allocator> Iterator for BoxedArrayIntoIter<T, N, A> {
255+
type Item = T;
256+
fn next(&mut self) -> Option<Self::Item> {
257+
self.inner.next()
258+
}
259+
260+
fn size_hint(&self) -> (usize, Option<usize>) {
261+
let len = self.len();
262+
(len, Some(len))
263+
}
264+
265+
#[inline]
266+
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
267+
where
268+
Fold: FnMut(Acc, Self::Item) -> Acc,
269+
{
270+
self.inner.fold(init, fold)
271+
}
272+
273+
fn count(self) -> usize {
274+
self.len()
275+
}
276+
277+
fn last(mut self) -> Option<Self::Item> {
278+
self.next_back()
279+
}
280+
281+
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
282+
self.inner.advance_by(n)
283+
}
284+
}
285+
286+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
287+
impl<T, const N: usize, A: Allocator> DoubleEndedIterator for BoxedArrayIntoIter<T, N, A> {
288+
fn next_back(&mut self) -> Option<Self::Item> {
289+
self.inner.next_back()
290+
}
291+
292+
#[inline]
293+
fn rfold<Acc, Fold>(self, init: Acc, rfold: Fold) -> Acc
294+
where
295+
Fold: FnMut(Acc, Self::Item) -> Acc,
296+
{
297+
self.inner.rfold(init, rfold)
298+
}
299+
300+
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
301+
self.inner.advance_back_by(n)
302+
}
303+
}
304+
305+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
306+
impl<T, const N: usize, A: Allocator> ExactSizeIterator for BoxedArrayIntoIter<T, N, A> {
307+
fn len(&self) -> usize {
308+
self.inner.len()
309+
}
310+
311+
fn is_empty(&self) -> bool {
312+
self.inner.is_empty()
313+
}
314+
}
315+
316+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
317+
impl<T, const N: usize, A: Allocator> FusedIterator for BoxedArrayIntoIter<T, N, A> {}
318+
319+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
320+
unsafe impl<T, const N: usize, A: Allocator> TrustedLen for BoxedArrayIntoIter<T, N, A> {}
321+
322+
#[cfg(not(no_global_oom_handling))]
323+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
324+
impl<T: Clone, const N: usize, A: Clone + Allocator> Clone for BoxedArrayIntoIter<T, N, A> {
325+
fn clone(&self) -> Self {
326+
Self { inner: self.inner.clone() }
327+
}
328+
}
329+
330+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
331+
impl<T: fmt::Debug, const N: usize, A: Allocator> fmt::Debug for BoxedArrayIntoIter<T, N, A> {
332+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333+
// Only print the elements that were not yielded yet: we cannot
334+
// access the yielded elements anymore.
335+
f.debug_tuple("BoxedArrayIntoIter").field(&self.as_slice()).finish()
336+
}
337+
}
338+
339+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
340+
impl<T, const N: usize, A: Allocator> IntoIterator for Box<[T; N], A> {
341+
type IntoIter = BoxedArrayIntoIter<T, N, A>;
342+
type Item = T;
343+
fn into_iter(self) -> BoxedArrayIntoIter<T, N, A> {
344+
BoxedArrayIntoIter { inner: (self as Box<[T], A>).into_vec().into_iter() }
345+
}
346+
}

library/alloc/src/vec/into_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ where
511511
#[doc(hidden)]
512512
#[unstable(issue = "none", feature = "std_internals")]
513513
#[rustc_unsafe_specialization_marker]
514-
pub trait NonDrop {}
514+
trait NonDrop {}
515515

516516
// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr
517517
// and thus we can't implement drop-handling

library/core/src/array/iter.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ impl<T, const N: usize> IntoIter<T, N> {
3434
}
3535
}
3636

37+
#[stable(feature = "boxed_array_value_iter", since = "CURRENT_RUSTC_VERSION")]
38+
impl<T, const N: usize> !Iterator for [T; N] {}
39+
3740
// Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator`
3841
// hides this implementation from explicit `.into_iter()` calls on editions < 2021,
3942
// so those calls will still resolve to the slice implementation, by reference.
@@ -365,7 +368,7 @@ unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
365368
#[doc(hidden)]
366369
#[unstable(issue = "none", feature = "std_internals")]
367370
#[rustc_unsafe_specialization_marker]
368-
pub trait NonDrop {}
371+
trait NonDrop {}
369372

370373
// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive
371374
// and thus we can't implement drop-handling

tests/ui/iterators/into-iter-on-arrays-2018.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::array::IntoIter;
55
use std::ops::Deref;
66
use std::rc::Rc;
77
use std::slice::Iter;
8+
use std::boxed::BoxedArrayIntoIter;
89

910
fn main() {
1011
let array = [0; 10];
@@ -15,9 +16,7 @@ fn main() {
1516
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
1617
//~| WARNING this changes meaning
1718

18-
let _: Iter<'_, i32> = Box::new(array).into_iter();
19-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
20-
//~| WARNING this changes meaning
19+
let _: BoxedArrayIntoIter<i32, 10> = Box::new(array).into_iter();
2120

2221
let _: Iter<'_, i32> = Rc::new(array).into_iter();
2322
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`

tests/ui/iterators/into-iter-on-arrays-2018.stderr

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
2-
--> $DIR/into-iter-on-arrays-2018.rs:14:34
2+
--> $DIR/into-iter-on-arrays-2018.rs:15:34
33
|
44
LL | let _: Iter<'_, i32> = array.into_iter();
55
| ^^^^^^^^^
@@ -19,16 +19,7 @@ LL + let _: Iter<'_, i32> = IntoIterator::into_iter(array);
1919
|
2020

2121
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
22-
--> $DIR/into-iter-on-arrays-2018.rs:18:44
23-
|
24-
LL | let _: Iter<'_, i32> = Box::new(array).into_iter();
25-
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
26-
|
27-
= warning: this changes meaning in Rust 2021
28-
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html>
29-
30-
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
31-
--> $DIR/into-iter-on-arrays-2018.rs:22:43
22+
--> $DIR/into-iter-on-arrays-2018.rs:21:43
3223
|
3324
LL | let _: Iter<'_, i32> = Rc::new(array).into_iter();
3425
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -37,7 +28,7 @@ LL | let _: Iter<'_, i32> = Rc::new(array).into_iter();
3728
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html>
3829

3930
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
40-
--> $DIR/into-iter-on-arrays-2018.rs:25:41
31+
--> $DIR/into-iter-on-arrays-2018.rs:24:41
4132
|
4233
LL | let _: Iter<'_, i32> = Array(array).into_iter();
4334
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -46,7 +37,7 @@ LL | let _: Iter<'_, i32> = Array(array).into_iter();
4637
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html>
4738

4839
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
49-
--> $DIR/into-iter-on-arrays-2018.rs:32:24
40+
--> $DIR/into-iter-on-arrays-2018.rs:31:24
5041
|
5142
LL | for _ in [1, 2, 3].into_iter() {}
5243
| ^^^^^^^^^
@@ -64,5 +55,5 @@ LL - for _ in [1, 2, 3].into_iter() {}
6455
LL + for _ in [1, 2, 3] {}
6556
|
6657

67-
warning: 5 warnings emitted
58+
warning: 4 warnings emitted
6859

tests/ui/iterators/into-iter-on-arrays-2021.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
use std::array::IntoIter;
55
use std::ops::Deref;
66
use std::rc::Rc;
7+
use std::boxed::BoxedArrayIntoIter;
78

89
fn main() {
910
let array = [0; 10];
1011

1112
// In 2021, the method dispatches to `IntoIterator for [T; N]`.
1213
let _: IntoIter<i32, 10> = array.into_iter();
13-
let _: IntoIter<i32, 10> = Box::new(array).into_iter();
14+
let _: BoxedArrayIntoIter<i32, 10> = Box::new(array).into_iter();
1415

1516
// The `array_into_iter` lint doesn't cover other wrappers that deref to an array.
1617
let _: IntoIter<i32, 10> = Rc::new(array).into_iter();

tests/ui/iterators/into-iter-on-arrays-lint.fixed

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,15 @@ fn main() {
2222
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
2323
//~| WARNING this changes meaning
2424

25-
Box::new(small).iter();
26-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
27-
//~| WARNING this changes meaning
28-
Box::new([1, 2]).iter();
29-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
30-
//~| WARNING this changes meaning
31-
Box::new(big).iter();
32-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
33-
//~| WARNING this changes meaning
34-
Box::new([0u8; 33]).iter();
35-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
36-
//~| WARNING this changes meaning
25+
Box::new(small).into_iter();
26+
Box::new([1, 2]).into_iter();
27+
Box::new(big).into_iter();
28+
Box::new([0u8; 33]).into_iter();
3729

38-
Box::new(Box::new(small)).iter();
39-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
40-
//~| WARNING this changes meaning
41-
Box::new(Box::new([1, 2])).iter();
42-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
43-
//~| WARNING this changes meaning
44-
Box::new(Box::new(big)).iter();
45-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
46-
//~| WARNING this changes meaning
47-
Box::new(Box::new([0u8; 33])).iter();
48-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
49-
//~| WARNING this changes meaning
30+
Box::new(Box::new(small)).into_iter();
31+
Box::new(Box::new([1, 2])).into_iter();
32+
Box::new(Box::new(big)).into_iter();
33+
Box::new(Box::new([0u8; 33])).into_iter();
5034

5135
// Expressions that should not
5236
(&[1, 2]).into_iter();

tests/ui/iterators/into-iter-on-arrays-lint.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,14 @@ fn main() {
2323
//~| WARNING this changes meaning
2424

2525
Box::new(small).into_iter();
26-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
27-
//~| WARNING this changes meaning
2826
Box::new([1, 2]).into_iter();
29-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
30-
//~| WARNING this changes meaning
3127
Box::new(big).into_iter();
32-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
33-
//~| WARNING this changes meaning
3428
Box::new([0u8; 33]).into_iter();
35-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
36-
//~| WARNING this changes meaning
3729

3830
Box::new(Box::new(small)).into_iter();
39-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
40-
//~| WARNING this changes meaning
4131
Box::new(Box::new([1, 2])).into_iter();
42-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
43-
//~| WARNING this changes meaning
4432
Box::new(Box::new(big)).into_iter();
45-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
46-
//~| WARNING this changes meaning
4733
Box::new(Box::new([0u8; 33])).into_iter();
48-
//~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
49-
//~| WARNING this changes meaning
5034

5135
// Expressions that should not
5236
(&[1, 2]).into_iter();

0 commit comments

Comments
 (0)