diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6d03c91..36a344f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -128,7 +128,7 @@ - [Reserved syntax](rust-2024/reserved-syntax.md) - [標準ライブラリ](rust-2024/standard-library.md) - [Changes to the prelude](rust-2024/prelude.md) - - [Add `IntoIterator` for `Box<[T]>`](rust-2024/intoiterator-box-slice.md) + - [Box<[T]> に対する IntoIterator の追加](rust-2024/intoiterator-box-slice.md) - [Newly unsafe functions](rust-2024/newly-unsafe-functions.md) - [Cargo](rust-2024/cargo.md) - [Cargo: Rust-version aware resolver](rust-2024/cargo-resolver.md) diff --git a/src/rust-2024/intoiterator-box-slice.md b/src/rust-2024/intoiterator-box-slice.md index ace51d9..1525cc4 100644 --- a/src/rust-2024/intoiterator-box-slice.md +++ b/src/rust-2024/intoiterator-box-slice.md @@ -1,20 +1,46 @@ -> **Rust Edition Guide は現在 Rust 2024 のアップデート作業に向けて翻訳作業中です。本ページはある時点での英語版をコピーしていますが、一部のリンクが動作しない場合や、最新情報が更新されていない場合があります。問題が発生した場合は、[原文(英語版)](https://doc.rust-lang.org/nightly/edition-guide/introduction.html)をご参照ください。** - + + +# Box<[T]> に対する IntoIterator の追加 + +## 概要 + + + +- ボックス化されたスライスは、*すべての*エディションで [`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` を呼び出すものに変わります。 + +[`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html +[`IntoIterator::into_iter`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#tymethod.into_iter + + + +## 詳細 + + +Rust 1.80 以前は、ボックス化されたスライスに対して `IntoIterator` が実装されていませんでした。以前のバージョンでは、ボックス化されたスライスに対して `.into_iter()` を呼び出すと、メソッド呼び出しが自動的に `Box<[T]>` から `&[T]` への参照外しを行い、`&T` の参照を返すイテレータが生成されました。たとえば、以下のコードは以前のエディションで動作していました: + + +```rust +// 以前のエディションでの動作例 +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` の実装が追加されました。これにより、スライスの要素を参照ではなく値としてイテレートできるようになります: + + + +```rust +// 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 以降では、値を返すイテレータを生成します。 + + +```rust,edition2024 +// 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 エディションに対応するために、次のコマンドを実行してください。 ```sh cargo fix --edition ``` + + +例えば、以下のコードは: + +```rust +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 + } +} +``` + + + +次のように修正されます: + + +```rust +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`] リントはすべてのエディションでデフォルトで警告を出す設定になっているため、手動でリントを無効化していなければ、移行前にすでに警告が表示されるはずです。 + + +[`boxed_slice_into_iter`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#boxed-slice-into-iter