- ボックス化されたスライスは、すべてのエディションで
IntoIterator
を実装します。 - 2024年以前のエディションでは、メソッド呼び出し構文(例:
boxed_slice.into_iter()
)でIntoIterator::into_iter
への呼び出しが隠蔽されるため、これまでどおりboxed_slice.into_iter()
は(&(*boxed_slice)).into_iter()
として解釈されます。 - Rust 2024 では、
boxed_slice.into_iter()
の意味がIntoIterator::into_iter
を呼び出すものに変わります。
Rust 1.80 以前は、ボックス化されたスライスに対して IntoIterator
が実装されていませんでした。以前のバージョンでは、ボックス化されたスライスに対して .into_iter()
を呼び出すと、メソッド呼び出しが自動的に Box<[T]>
から &[T]
への参照外しを行い、&T
の参照を返すイテレータが生成されました。たとえば、以下のコードは以前のエディションで動作していました:
// 以前のエディションでの動作例
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
// 注意:1.80以前のバージョンでは .into_iter() の呼び出しが必要です
for x in my_boxed_slice.into_iter() {
// Rust 2024 以前のエディションでは、x の型は &u32 です
}
Rust 1.80 では、ボックス化されたスライスに対して IntoIterator
の実装が追加されました。これにより、スライスの要素を参照ではなく値としてイテレートできるようになります:
// 1.80以降、すべてのエディションでの新しい動作
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
for x in my_boxed_slice { // .into_iter() の呼び出しは不要になっています
// x の型は u32 です
}
この例は、すべてのエディションで許可されています。というのも、以前は for
ループが .into_iter()
のように自動的に参照外しを行わなかったため、そもそもエラーになっていたからです。
しかし、本来であれば、これは破壊的変更となる可能性があります。なぜなら、これまで .into_iter()
を明示的に呼び出していたコードの動作が、参照を返すイテレータから値を返すイテレータへと変わってしまうからです。この問題を解決するために、ボックス化されたスライスの .into_iter()
の動作はエディションによって異なります。2024年以前のエディションでは、これまでどおり参照を返すイテレータを生成します。Rust 2024 以降では、値を返すイテレータを生成します。
// 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()
// .into_iter() を明示的に呼び出していた古いコードの例
for x in my_boxed_slice.into_iter() {
// Edition 2024 では、x の型は u32 になります
}
boxed_slice_into_iter
リントは、ボックス化されたスライスに対する .into_iter()
の呼び出しを .iter()
に自動で置き換え、従来どおり参照を返すように修正します。このリントは rust-2024-compatibility
リントグループの一部であり、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 の型は &u32
}
}
次のように修正されます:
fn main() {
let my_boxed_slice: Box<[u32]> = vec![1, 2, 3].into_boxed_slice();
for x in my_boxed_slice.iter() {
// x の型は &u32
}
}
boxed_slice_into_iter
リントはすべてのエディションでデフォルトで警告を出す設定になっているため、手動でリントを無効化していなければ、移行前にすでに警告が表示されるはずです。