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,否则在迁移之前您应该已经看到它。