diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6d03c91..8fc6888 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -122,8 +122,8 @@ - [`unsafe_op_in_unsafe_fn` warning](rust-2024/unsafe-op-in-unsafe-fn.md) - [Disallow references to `static mut`](rust-2024/static-mut-references.md) - [Never type fallback change](rust-2024/never-type-fallback.md) - - [Macro fragment specifiers](rust-2024/macro-fragment-specifiers.md) - - [Missing macro fragment specifiers](rust-2024/missing-macro-fragment-specifiers.md) + - [マクロフラグメント指定子](rust-2024/macro-fragment-specifiers.md) + - [未使用のマクロフラグメント指定子](rust-2024/missing-macro-fragment-specifiers.md) - [`gen` keyword](rust-2024/gen-keyword.md) - [Reserved syntax](rust-2024/reserved-syntax.md) - [標準ライブラリ](rust-2024/standard-library.md) diff --git a/src/rust-2024/macro-fragment-specifiers.md b/src/rust-2024/macro-fragment-specifiers.md index 3a0badf..8948fc4 100644 --- a/src/rust-2024/macro-fragment-specifiers.md +++ b/src/rust-2024/macro-fragment-specifiers.md @@ -1,20 +1,51 @@ -> **Rust Edition Guide は現在 Rust 2024 のアップデート作業に向けて翻訳作業中です。本ページはある時点での英語版をコピーしていますが、一部のリンクが動作しない場合や、最新情報が更新されていない場合があります。問題が発生した場合は、[原文(英語版)](https://doc.rust-lang.org/nightly/edition-guide/introduction.html)をご参照ください。** - + + +# マクロフラグメント指定子 + +## 概要 + + + +- [フラグメント指定子] `expr` が、`const` 式と `_` 式をサポートするようになりました。 +- 後方互換性のために、フラグメント指定子 `expr_2021` が追加されました。 + +[フラグメント指定子]: https://doc.rust-lang.org/reference/macros-by-example.html#metavariables + + + +## 詳細 + +Rust に新しい文法を導入するとき、後方互換性のために既存の `macro_rules` フラグメント指定子を新しい記法の対象外とする場合があります。 +すなわち、古いフラグメント指定子の新記法のサポートが次の新エディションまで延期されることがあるのです。 + + + +1.79 で導入された [`const` 式]と 1.59 で導入された [`_` 式]では、実際にそのような決定がなされました。 +2021 エディション以前では、フラグメント指定子 `expr` はこれらの新記法にマッチ**しません**。 +理由は以下のコードを考えるとわかります。 + +```rust,edition2021 +macro_rules! example { + ($e:expr) => { println!("前者"); }; + (const $e:expr) => { println!("後者"); }; +} + +fn main() { + example!(const { 1 + 1 }); +} +``` + + +2021 エディションでは、マクロは**後者**のルールにマッチします。 +2021 以前のエディションで `expr` が新文法である `const` 式にマッチしてしまうようになると、マクロは**前者**のルールにマッチするようになってしまいます。 +これは破壊的変更です。 + + + +2024 エディションから、指定子 `expr` が `const` 式と `_` 式にもマッチするようになりました。 +過去の挙動もサポートするために、これらにマッチ**しない**フラグメント指定子 `expr_2021` も新たに提供されています。 + +[`const` 式]: https://doc.rust-lang.org/reference/expressions/block-expr.html#const-blocks +[`_` 式]: https://doc.rust-lang.org/reference/expressions/underscore-expr.html + + + +## 移行 + + +[`edition_2024_expr_fragment_specifier`] リントで、`expr` 指定子をすべて `expr_2021` に自動的に書き換え、マクロの挙動が変わらないようにできます。 +このリントは、自動エディション移行に含まれる `rust-2024-compatibility` リントグループの一部です。 +コードを Rust 2024 互換に移行するには、以下を実行します。 ```sh cargo fix --edition ``` + +**ほとんどの**場合、指定子を `expr` のままにしておき、新記法をサポートするべきでしょう。 +マクロの定義を再確認して、`const` や `_` にマッチしうるようなルールの重複がないかを再確認してください。 +新記法をサポートしてもよければ、リントの自動修正を戻せばよいです。 + + + +あるいは、エディション移行ツールを使わずに手動で確認したい場合は、以下のリントをオンにしてください。 + +```rust +// クレートのトップレベルに以下を追加すると手動移行できる +#![warn(edition_2024_expr_fragment_specifier)] +``` + + + +[`edition_2024_expr_fragment_specifier`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#edition-2024-expr-fragment-specifier diff --git a/src/rust-2024/missing-macro-fragment-specifiers.md b/src/rust-2024/missing-macro-fragment-specifiers.md index 232bdc4..180478c 100644 --- a/src/rust-2024/missing-macro-fragment-specifiers.md +++ b/src/rust-2024/missing-macro-fragment-specifiers.md @@ -1,21 +1,45 @@ -> **Rust Edition Guide は現在 Rust 2024 のアップデート作業に向けて翻訳作業中です。本ページはある時点での英語版をコピーしていますが、一部のリンクが動作しない場合や、最新情報が更新されていない場合があります。問題が発生した場合は、[原文(英語版)](https://doc.rust-lang.org/nightly/edition-guide/introduction.html)をご参照ください。** - + + +# 未使用のマクロフラグメント指定子 + +## 概要 + + + +- [`missing_fragment_specifier`] リントがエラー扱いされるようになります。 + +[`missing_fragment_specifier`]: https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#missing-fragment-specifier + + + +## 詳細 + + +[`missing_fragment_specifier`] リントは、マクロ定義 (`macro_rules!`) 内の**未使用の**パターン中の(`$e` のような)メタ変数であって、(`:expr` といった)フラグメント指定子のないものを検出します。 +2024 エディションからはこのリントはエラー扱いになります。 ```rust,compile_fail macro_rules! foo { () => {}; ($name) => { }; // ERROR: missing fragment specifier + // エラー: フラグメント指定子がありません } fn main() { @@ -23,16 +47,45 @@ fn main() { } ``` + +`foo!($name)` のように、フラグメント指定子のないメタ変数を含むルールにマッチするマクロ呼び出しは、全エディションでエラーです。 +一方、そのようなマクロを定義すること自体はエラーではありません(これを検出するリントは 1.17 から追加されています)。 + + + +本当ならこのリントを全エディションでエラー扱いしたいところですが、あまりにも影響が大きすぎるため、ひとまず Rust 2024 以降でだけエラー扱いすることになりました。[^future-incompat] + + +[^future-incompat]: このリントは "future-incompatible" な(将来的に非互換になる)警告に分類されており、将来のリリースでは全エディションでエラー扱いになる予定であるとされています。 +詳細は [#40107] をご参照ください。 [#40107]: https://github.com/rust-lang/rust/issues/40107 + +## 移行 + + + +コードを 2024 エディションに移行するには、上記のような未使用のルールを削除してください。 +[`missing_fragment_specifier`] リントは全エディションで有効化されており、このようなマクロに対して警告が出ます。 + + +これに対する自動移行は提供されていません。 +このようなマクロはまずないと思われます。 +このリントは Rust 1.17 から future-incompatible なリントになり、Rust 1.20 からデフォルトで必ずエラーになり、1.82 からは依存ライブラリ中であっても警告が出るようになっています。