为 Box<[T]>
添加 IntoIterator
概述
- Boxed slices 在所有版本中都实现了
IntoIterator
。 - 当使用方法调用语法(即
boxed_slice.into_iter()
)时,在 2024 年之前的版本中,对IntoIterator::into_iter
的调用是隐藏的。因此,boxed_slice.into_iter()
仍然像以前一样解析为(&(*boxed_slice)).into_iter()
。 - 在 Rust 2024 中,
boxed_slice.into_iter()
的含义更改为调用IntoIterator::into_iter
。
详情
在 Rust 1.80 之前,IntoIterator
没有为 boxed slices 实现。在之前的版本中,如果在 boxed slice 上调用 .into_iter()
,方法调用会自动从 Box<[T]>
解引用为 &[T]
,并返回一个迭代器,该迭代器产生 &T
的引用。例如,以下代码在之前的版本中可以工作
#![allow(unused)] fn main() { // Example of behavior in previous editions. let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice(); // Note: .into_iter() was required in versions older than 1.80 for x in my_boxed_slice.into_iter() { // x is of type &u32 in editions prior to 2024 } }
在 Rust 1.80 中,为 boxed slices 添加了 IntoIterator
的实现。这允许通过值而不是通过引用的方式迭代 slice 的元素
#![allow(unused)] fn main() { // NEW as of 1.80, all editions let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice(); for x in my_boxed_slice { // notice no need for calling .into_iter() // x is of type u32 } }
此示例在所有版本中都允许,因为以前这是一个错误,因为 for
循环不像 .into_iter()
方法调用那样自动解引用。
然而,这通常会是一个破坏性更改,因为在 boxed slice 上手动调用 .into_iter()
的现有代码会从拥有一个引用迭代器更改为拥有一个值迭代器。为了解决这个问题,在 boxed slice 上调用 .into_iter()
的方法具有版本依赖的行为。在 2024 年之前的版本中,它继续返回一个引用迭代器,而在 2024 版本及更高版本中,它返回一个值迭代器。
#![allow(unused)] fn main() { // Example of changed behavior in Edition 2024 let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice(); // Example of old code that still manually calls .into_iter() for x in my_boxed_slice.into_iter() { // x is now type u32 in Edition 2024 } }
迁移
boxed_slice_into_iter
lint 将自动修改对 boxed slices 上 .into_iter()
的任何调用,以调用 .iter()
来保留产生引用的旧行为。此 lint 是 rust-2024-compatibility
lint 组的一部分,该 lint 组在运行 cargo fix --edition
时会自动应用。要迁移您的代码以兼容 Rust 2024 版本,请运行
cargo fix --edition
例如,这将更改
fn main() { let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice(); for x in my_boxed_slice.into_iter() { // x is of type &u32 } }
变为
fn main() { let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice(); for x in my_boxed_slice.iter() { // x is of type &u32 } }
boxed_slice_into_iter
lint 默认在所有版本上都发出警告,因此除非您手动静音了该 lint,否则在迁移之前您应该已经看到它。