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} ;
166205use core:: pin:: Pin ;
167206use core:: ptr:: { self , addr_of_mut, NonNull , Unique } ;
207+ use core:: slice;
168208use core:: task:: { Context , Poll } ;
169209
170210#[ cfg( not( no_global_oom_handling) ) ]
@@ -177,6 +217,7 @@ use crate::raw_vec::RawVec;
177217use crate :: str:: from_boxed_utf8_unchecked;
178218#[ cfg( not( no_global_oom_handling) ) ]
179219use crate :: string:: String ;
220+ use crate :: vec;
180221#[ cfg( not( no_global_oom_handling) ) ]
181222use 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" ) ]
20852171impl FromIterator < char > for Box < str > {
0 commit comments