Skip to content

Commit a398018

Browse files
Add the impls for Box<[T]>: IntoIterator
Co-authored-by: ltdk <[email protected]>
1 parent 6727130 commit a398018

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

Diff for: alloc/src/boxed.rs

+86
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,45 @@
135135
//! is not allowed. For more guidance on working with box from unsafe code, see
136136
//! [rust-lang/unsafe-code-guidelines#326][ucg#326].
137137
//!
138+
//! # Editions
139+
//!
140+
//! A special case exists for the implementation of `IntoIterator` for arrays on the Rust 2021
141+
//! edition, as documented [here][array]. Unfortunately, it was later found that a similar
142+
//! workaround should be added for boxed slices, and this was applied in the 2024 edition.
143+
//!
144+
//! Specifically, `IntoIterator` is implemented for `Box<[T]>` on all editions, but specific calls
145+
//! to `into_iter()` for boxed slices will defer to the slice implementation on editions before
146+
//! 2024:
147+
//!
148+
#![cfg_attr(bootstrap, doc = "```rust,edition2021,ignore")]
149+
#![cfg_attr(not(bootstrap), doc = "```rust,edition2021")]
150+
//! // Rust 2015, 2018, and 2021:
151+
//!
152+
//! # #![allow(boxed_slice_into_iter)] // override our `deny(warnings)`
153+
//! let boxed_slice: Box<[i32]> = vec![0; 3].into_boxed_slice();
154+
//!
155+
//! // This creates a slice iterator, producing references to each value.
156+
//! for item in boxed_slice.into_iter().enumerate() {
157+
//! let (i, x): (usize, &i32) = item;
158+
//! println!("boxed_slice[{i}] = {x}");
159+
//! }
160+
//!
161+
//! // The `boxed_slice_into_iter` lint suggests this change for future compatibility:
162+
//! for item in boxed_slice.iter().enumerate() {
163+
//! let (i, x): (usize, &i32) = item;
164+
//! println!("boxed_slice[{i}] = {x}");
165+
//! }
166+
//!
167+
//! // You can explicitly iterate a boxed slice by value using `IntoIterator::into_iter`
168+
//! for item in IntoIterator::into_iter(boxed_slice).enumerate() {
169+
//! let (i, x): (usize, i32) = item;
170+
//! println!("boxed_slice[{i}] = {x}");
171+
//! }
172+
//! ```
173+
//!
174+
//! Similar to the array implementation, this may be modified in the future to remove this override,
175+
//! and it's best to avoid relying on this edition-dependent behavior if you wish to preserve
176+
//! compatibility with future versions of the compiler.
138177
//!
139178
//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
140179
//! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326
@@ -165,6 +204,7 @@ use core::ops::{
165204
};
166205
use core::pin::Pin;
167206
use core::ptr::{self, addr_of_mut, NonNull, Unique};
207+
use core::slice;
168208
use core::task::{Context, Poll};
169209

170210
#[cfg(not(no_global_oom_handling))]
@@ -177,6 +217,7 @@ use crate::raw_vec::RawVec;
177217
use crate::str::from_boxed_utf8_unchecked;
178218
#[cfg(not(no_global_oom_handling))]
179219
use crate::string::String;
220+
use crate::vec;
180221
#[cfg(not(no_global_oom_handling))]
181222
use crate::vec::Vec;
182223

@@ -2080,6 +2121,51 @@ impl<I> FromIterator<I> for Box<[I]> {
20802121
}
20812122
}
20822123

2124+
/// This implementation is required to make sure that the `Box<[I]>: IntoIterator`
2125+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
2126+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2127+
impl<I, A: Allocator> !Iterator for Box<[I], A> {}
2128+
2129+
/// This implementation is required to make sure that the `&Box<[I]>: IntoIterator`
2130+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
2131+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2132+
impl<'a, I, A: Allocator> !Iterator for &'a Box<[I], A> {}
2133+
2134+
/// This implementation is required to make sure that the `&mut Box<[I]>: IntoIterator`
2135+
/// implementation doesn't overlap with `IntoIterator for T where T: Iterator` blanket.
2136+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2137+
impl<'a, I, A: Allocator> !Iterator for &'a mut Box<[I], A> {}
2138+
2139+
// Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator`
2140+
// hides this implementation from explicit `.into_iter()` calls on editions < 2024,
2141+
// so those calls will still resolve to the slice implementation, by reference.
2142+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2143+
impl<I, A: Allocator> IntoIterator for Box<[I], A> {
2144+
type IntoIter = vec::IntoIter<I, A>;
2145+
type Item = I;
2146+
fn into_iter(self) -> vec::IntoIter<I, A> {
2147+
self.into_vec().into_iter()
2148+
}
2149+
}
2150+
2151+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2152+
impl<'a, I, A: Allocator> IntoIterator for &'a Box<[I], A> {
2153+
type IntoIter = slice::Iter<'a, I>;
2154+
type Item = &'a I;
2155+
fn into_iter(self) -> slice::Iter<'a, I> {
2156+
self.iter()
2157+
}
2158+
}
2159+
2160+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
2161+
impl<'a, I, A: Allocator> IntoIterator for &'a mut Box<[I], A> {
2162+
type IntoIter = slice::IterMut<'a, I>;
2163+
type Item = &'a mut I;
2164+
fn into_iter(self) -> slice::IterMut<'a, I> {
2165+
self.iter_mut()
2166+
}
2167+
}
2168+
20832169
#[cfg(not(no_global_oom_handling))]
20842170
#[stable(feature = "boxed_str_from_iter", since = "CURRENT_RUSTC_VERSION")]
20852171
impl FromIterator<char> for Box<str> {

Diff for: core/src/slice/iter.rs

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ use crate::ptr::{self, without_provenance, without_provenance_mut, NonNull};
1616

1717
use super::{from_raw_parts, from_raw_parts_mut};
1818

19+
#[stable(feature = "boxed_slice_into_iter", since = "CURRENT_RUSTC_VERSION")]
20+
impl<T> !Iterator for [T] {}
21+
1922
#[stable(feature = "rust1", since = "1.0.0")]
2023
impl<'a, T> IntoIterator for &'a [T] {
2124
type Item = &'a T;

0 commit comments

Comments
 (0)