Skip to content

Commit c9ddf51

Browse files
committed
Add IntoIterator for Box<[T]> in 2024
1 parent a04d063 commit c9ddf51

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
- [Rust 2024 🚧](rust-2024/index.md)
4141
- [Additions to the prelude](rust-2024/prelude.md)
42+
- [Add `IntoIterator` for `Box<[T]>`](rust-2024/intoiterator-box-slice.md)
4243
- [`unsafe_op_in_unsafe_fn` warning](rust-2024/unsafe-op-in-unsafe-fn.md)
4344
- [RPIT lifetime capture](rust-2024/rpit-lifetime-capture.md)
4445
- [Disallow references to `static mut`](rust-2024/static-mut-reference.md)
+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Add `IntoIterator` for `Box<[T]>`
2+
3+
🚧 The 2024 Edition has not yet been released and hence this section is still "under construction".
4+
More information may be found in the tracking issue at <https://github.com/rust-lang/rust/issues/123759>.
5+
6+
## Summary
7+
8+
- Boxed slices implement [`IntoIterator`] in *all* editions.
9+
- Calls to [`IntoIterator::into_iter`] are *hidden* in editions prior to 2024 when using method call syntax (i.e., `boxed_slice.into_iter()`). So, `boxed_slice.into_iter()` still resolves to `(&(*boxed_slice)).into_iter()` as it has before.
10+
- `boxed_slice.into_iter()` changes meaning to be the call [`IntoIterator::into_iter`] in Rust 2024.
11+
12+
[`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
13+
[`IntoIterator::into_iter`]: ../../std/iter/trait.IntoIterator.html#tymethod.into_iter
14+
15+
## Details
16+
17+
Until Rust 1.80, `IntoIterator` was not implemented for boxed slices. In prior versions, if you called `.into_iter()` on a boxed slice, the method call would automatically dereference from `Box<[T]>` to `&[T]`, and return an iterator that yielded references of `&T`. For example, the following worked in prior versions:
18+
19+
```rust
20+
// Example of behavior in previous editions.
21+
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
22+
// Note: .into_iter() was required in versions older than 1.80
23+
for x in my_boxed_slice.into_iter() {
24+
// x is of type &u32 in editions prior to 2024
25+
}
26+
```
27+
28+
In Rust 1.80, implementations of `IntoIterator` were added for boxed slices. This allows iterating over elements of the slice by-value instead of by-reference:
29+
30+
```rust
31+
// NEW as of 1.80, all editions
32+
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
33+
for x in my_boxed_slice { // notice no need for calling .into_iter()
34+
// x is of type u32
35+
}
36+
```
37+
38+
This example is allowed on all editions because previously this was an error since `for` loops do not automatically dereference like the `.into_iter()` method call does.
39+
40+
However, this would normally be a breaking change because existing code that manually called `.into_iter()` on a boxed slice would change from having an iterator over references to an iterator over values. To resolve this problem, method calls of `.into_iter()` on boxed slices have edition-dependent behavior. In editions before 2024, it continues to return an iterator over references, and starting in Edition 2024 it returns an iterator over values.
41+
42+
<!-- TODO: edition2024 -->
43+
```rust
44+
// Example of changed behavior in Edition 2024
45+
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
46+
// Example of old code that still manually calls .into_iter()
47+
for x in my_boxed_slice.into_iter() {
48+
// x is now type u32 in Edition 2024
49+
}
50+
```
51+
52+
## Migration
53+
54+
The [`boxed_slice_into_iter`] lint will automatically modify any calls to `.into_iter()` on boxed slices to call `.iter()` instead to retain the old behavior of yielding references. This lint is part of the `rust-2024-compatibility` lint group, which will automatically be applied when running `cargo fix --edition`. To migrate your code to be Rust 2024 Edition compatible, run:
55+
56+
```sh
57+
cargo fix --edition
58+
```
59+
60+
For example, this will change:
61+
62+
```rust
63+
fn main() {
64+
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
65+
for x in my_boxed_slice.into_iter() {
66+
// x is of type &u32
67+
}
68+
}
69+
```
70+
71+
to be:
72+
73+
```rust
74+
fn main() {
75+
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
76+
for x in my_boxed_slice.iter() {
77+
// x is of type &u32
78+
}
79+
}
80+
```
81+
82+
The [`boxed_slice_into_iter`] lint is defaulted to warn on all editions, so unless you have manually silenced the lint, you should already see it before you migrate.
83+
84+
[`boxed_slice_into_iter`]: ../../rustc/lints/listing/warn-by-default.html#boxed-slice-into-iter

0 commit comments

Comments
 (0)