|
| 1 | +<!-- |
1 | 2 | # Or patterns in macro-rules |
| 3 | +--> |
2 | 4 |
|
| 5 | +# マクロ規則における OR パターン |
| 6 | + |
| 7 | +<!-- |
3 | 8 | ## Summary |
| 9 | +--> |
| 10 | + |
| 11 | +## 概要 |
4 | 12 |
|
| 13 | +<!-- |
5 | 14 | - How patterns work in `macro_rules` macros changes slightly: |
6 | 15 | - `$_:pat` in `macro_rules` now matches usage of `|` too: e.g. `A | B`. |
7 | 16 | - The new `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`. |
8 | 17 | - `$_:pat_param` is available in all editions. |
| 18 | +--> |
| 19 | + |
| 20 | +- `macro_rules` におけるパターンの挙動がほんの少し変更されました: |
| 21 | + - `macro_rules` において、`$_:pat` で `|` を使ったパターンにもマッチするようになりました。例えば、`A | B` にマッチします。 |
| 22 | + - 新しく導入された `$_:pat_param` は、かつての `$_:pat` と同じ挙動を再現します。すなわち、こちらは(トップレベルの)`|` にはマッチしません。 |
| 23 | + - `$_:pat_param` は全てのエディションで使用可能です。 |
| 24 | + |
| 25 | + |
9 | 26 |
|
| 27 | +<!-- |
10 | 28 | ## Details |
| 29 | +--> |
11 | 30 |
|
| 31 | +## 詳細 |
| 32 | + |
| 33 | +<!-- |
12 | 34 | Starting in Rust 1.53.0, [patterns](https://doc.rust-lang.org/stable/reference/patterns.html) |
13 | 35 | are extended to support `|` nested anywhere in the pattern. |
14 | 36 | This enables you to write `Some(1 | 2)` instead of `Some(1) | Some(2)`. |
15 | 37 | Since this was simply not allowed before, this is not a breaking change. |
| 38 | +--> |
| 39 | + |
| 40 | +Rust 1.53.0 から、[パターン](https://doc.rust-lang.org/stable/reference/patterns.html)中のどこでも、`|` をネストして使えるようになりました。 |
| 41 | +これにより、`Some(1) | Some(2)` でなく `Some(1 | 2)` と書くことができるようになりました。 |
| 42 | +今まではこうは書けなかったので、これは破壊的変更ではありません。 |
16 | 43 |
|
| 44 | +<!-- |
17 | 45 | However, this change also affects [`macro_rules` macros](https://doc.rust-lang.org/stable/reference/macros-by-example.html). |
18 | 46 | Such macros can accept patterns using the `:pat` fragment specifier. |
19 | 47 | Currently, `:pat` does *not* match top level `|`, since before Rust 1.53, |
20 | 48 | not all patterns (at all nested levels) could contain a `|`. |
21 | 49 | Macros that accept patterns like `A | B`, |
22 | 50 | such as [`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html) |
23 | 51 | use something like `$($_:pat)|+`. |
| 52 | +--> |
24 | 53 |
|
| 54 | +ところが、この変更は [`macro_rules` で定義されたマクロ](https://doc.rust-lang.org/stable/reference/macros-by-example.html) にも影響します。 |
| 55 | +`macro_rules` では、`:pat` というフラグメント指定子で、パターンを受け付けることができます。 |
| 56 | +現在のところ、`:pat` はトップレベルの `|` にマッチ*しません*。 |
| 57 | +なぜなら Rust 1.53 以前は、全てのパターンが(どのネストレベルにでも)`|` を含むことができるわけではなかったからです。 |
| 58 | +[`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html) のように、 |
| 59 | +`A | B` のようなパターンを受け付けるマクロを書くには、 |
| 60 | +`$($_:pat)|+` のような書き方をしなくてはなりませんでした。 |
| 61 | + |
| 62 | +<!-- |
25 | 63 | Because this would potentially break existing macros, the meaning of `:pat` did |
26 | 64 | not change in Rust 1.53.0 to include `|`. Instead, that change happens in Rust 2021. |
27 | 65 | In the new edition, the `:pat` fragment specifier *will* match `A | B`. |
| 66 | +--> |
| 67 | + |
| 68 | +既存のマクロを壊す可能性があるため、Rust 1.53.0 では `:pat` が `|` を含むことができるようには変更されませんでした。 |
| 69 | +代わりに、Rust 2021 で変更がなされました。 |
| 70 | +新しいエディションでは、`:pat` フラグメント指定子は `A | B` にマッチ*します*。 |
28 | 71 |
|
| 72 | +<!-- |
29 | 73 | `$_:pat` fragments in Rust 2021 cannot be followed by an explicit `|`. Since there are times |
30 | 74 | that one still wishes to match pattern fragments followed by a `|`, the fragment specified `:pat_param` |
31 | 75 | has been added to retain the older behavior. |
| 76 | +--> |
32 | 77 |
|
| 78 | +Rust 2021 では、`$_:pat` フラグメントに `|` そのものを続けることはできません。 |
| 79 | +パターンフラグメントに `|` が続いてるものにマッチさせたいような場合は、新しく追加された `:pat_param` が過去と同じ挙動を示すようになっています。 |
| 80 | + |
| 81 | +<!-- |
33 | 82 | It's important to remember that editions are _per crate_, so the only relevant edition is the edition |
34 | 83 | of the crate where the macro is defined. The edition of the crate where the macro is used does not |
35 | 84 | change how the macro works. |
| 85 | +--> |
| 86 | + |
| 87 | +ただし、エディションは<!-- -->_クレートごとに_<!-- -->設定されることに注意してください。 |
| 88 | +つまり、マクロが定義されているクレートのエディションだけが関係します。 |
| 89 | +マクロを使用する方のクレートのエディションは、マクロの挙動に影響しません。 |
36 | 90 |
|
| 91 | +<!-- |
37 | 92 | ## Migration |
| 93 | +--> |
| 94 | + |
| 95 | +## 移行 |
38 | 96 |
|
| 97 | +<!-- |
39 | 98 | A lint, `rust_2021_incompatible_or_patterns`, gets triggered whenever there is a use `$_:pat` which |
40 | 99 | will change meaning in Rust 2021. |
| 100 | +--> |
41 | 101 |
|
| 102 | +`$_:pat` が使われている場所のうち、Rust 2021 で意味が変わるようなものに対しては、`rust_2021_incompatible_or_patterns` というリントが発生します。 |
| 103 | + |
| 104 | +<!-- |
42 | 105 | You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by |
43 | 106 | running: |
| 107 | +--> |
| 108 | + |
| 109 | +コードを自動的に Rust 2021 エディションに適合するよう自動移行するか、既に適合するものであることを確認するためには、以下のように実行すればよいです: |
44 | 110 |
|
45 | 111 | ```sh |
46 | 112 | cargo fix --edition |
47 | 113 | ``` |
48 | 114 |
|
| 115 | +<!-- |
49 | 116 | If you have a macro which relies on `$_:pat` not matching the top level use of `|` in patterns, |
50 | 117 | you'll need to change each occurrence of `$_:pat` to `$_:pat_param`. |
| 118 | +--> |
51 | 119 |
|
| 120 | +あなたのマクロが、`$_:pat` がトップレベルの `|` にマッチしないという挙動に依存している場合は、 |
| 121 | +`$_:pat` を `$_:pat_param` に書き換える必要があります。 |
| 122 | + |
| 123 | +<!-- |
52 | 124 | For example: |
| 125 | +--> |
| 126 | + |
| 127 | +例えば以下のようになります。 |
53 | 128 |
|
54 | 129 | ```rust |
55 | 130 | macro_rules! my_macro { |
56 | 131 | ($x:pat | $y:pat) => { |
57 | 132 | // TODO: implementation |
58 | | - } |
| 133 | + // TODO: 実装 |
| 134 | + } |
59 | 135 | } |
60 | 136 |
|
61 | 137 | // This macro works in Rust 2018 since `$x:pat` does not match against `|`: |
| 138 | +// Rust 2018 では、`$x:pat` が `|` にマッチしないので、以下のマクロは正常に動きます: |
62 | 139 | my_macro!(1 | 2); |
63 | 140 |
|
64 | 141 | // In Rust 2021 however, the `$_:pat` fragment matches `|` and is not allowed |
65 | 142 | // to be followed by a `|`. To make sure this macro still works in Rust 2021 |
66 | 143 | // change the macro to the following: |
| 144 | +// 一方 Rust 2021 では、`$_:pat` フラグメントは `|` にもマッチし、 |
| 145 | +// `|` が続くのは許されなくなりました。 |
| 146 | +// Rust 2021 でもマクロが動作するためには、マクロを以下のように変更しなくてはなりません: |
67 | 147 | macro_rules! my_macro { |
68 | 148 | ($x:pat_param | $y:pat) => { // <- this line is different |
| 149 | + // この行を変えた |
69 | 150 | // TODO: implementation |
| 151 | + // TODO: 実装 |
70 | 152 | } |
71 | 153 | } |
72 | | -``` |
| 154 | +``` |
0 commit comments