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,48 @@ impl<I> FromIterator<I> for Box<[I]> {
20802121 }
20812122}
20822123
2124+ /// `Box` is fundamental, so coherence needs help understanding these impls are okay.
2125+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2126+ impl < I , A : Allocator > !Iterator for Box < [ I ] , A > { }
2127+
2128+ /// `Box` is fundamental, so coherence needs help understanding these impls are okay.
2129+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2130+ impl < ' a , I , A : Allocator > !Iterator for & ' a Box < [ I ] , A > { }
2131+
2132+ /// `Box` is fundamental, so coherence needs help understanding these impls are okay.
2133+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2134+ impl < ' a , I , A : Allocator > !Iterator for & ' a mut Box < [ I ] , A > { }
2135+
2136+ // Note: the `#[rustc_skip_during_method_dispatch(boxed_slice)]` on `trait IntoIterator`
2137+ // hides this implementation from explicit `.into_iter()` calls on editions < 2024,
2138+ // so those calls will still resolve to the slice implementation, by reference.
2139+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2140+ impl < I , A : Allocator > IntoIterator for Box < [ I ] , A > {
2141+ type IntoIter = vec:: IntoIter < I , A > ;
2142+ type Item = I ;
2143+ fn into_iter ( self ) -> vec:: IntoIter < I , A > {
2144+ self . into_vec ( ) . into_iter ( )
2145+ }
2146+ }
2147+
2148+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2149+ impl < ' a , I , A : Allocator > IntoIterator for & ' a Box < [ I ] , A > {
2150+ type IntoIter = slice:: Iter < ' a , I > ;
2151+ type Item = & ' a I ;
2152+ fn into_iter ( self ) -> slice:: Iter < ' a , I > {
2153+ self . iter ( )
2154+ }
2155+ }
2156+
2157+ #[ stable( feature = "boxed_slice_into_iter" , since = "CURRENT_RUSTC_VERSION" ) ]
2158+ impl < ' a , I , A : Allocator > IntoIterator for & ' a mut Box < [ I ] , A > {
2159+ type IntoIter = slice:: IterMut < ' a , I > ;
2160+ type Item = & ' a mut I ;
2161+ fn into_iter ( self ) -> slice:: IterMut < ' a , I > {
2162+ self . iter_mut ( )
2163+ }
2164+ }
2165+
20832166#[ cfg( not( no_global_oom_handling) ) ]
20842167#[ stable( feature = "box_slice_clone" , since = "1.3.0" ) ]
20852168impl < T : Clone , A : Allocator + Clone > Clone for Box < [ T ] , A > {
0 commit comments