]> git.proxmox.com Git - rustc.git/blobdiff - src/doc/edition-guide/src/rust-2021/or-patterns-macro-rules.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / edition-guide / src / rust-2021 / or-patterns-macro-rules.md
index 451b0e5f6425937881f5a04e36f0b378134f22b3..58d6d5517e63c25081f5077c26b0cede51c9ce6b 100644 (file)
@@ -2,6 +2,11 @@
 
 ## Summary
 
+- How patterns work in `macro_rules` macros changes slightly:
+       - `$_:pat` in `macro_rules` now matches usage of `|` too: e.g. `A | B`.
+       - The new `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`.
+       - `$_:pat_param` is available in all editions.
+
 ## Details
 
 Starting in Rust 1.53.0, [patterns](https://doc.rust-lang.org/stable/reference/patterns.html)
@@ -11,18 +16,57 @@ Since this was simply not allowed before, this is not a breaking change.
 
 However, this change also affects [`macro_rules` macros](https://doc.rust-lang.org/stable/reference/macros-by-example.html).
 Such macros can accept patterns using the `:pat` fragment specifier.
-Currently, `:pat` does *not* match `|`, since before Rust 1.53,
+Currently, `:pat` does *not* match top level `|`, since before Rust 1.53,
 not all patterns (at all nested levels) could contain a `|`.
 Macros that accept patterns like `A | B`,
 such as [`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html)
-use something like `$($_:pat)|+`.
-Because we don't want to break any existing macros,
-we did *not* change the meaning of `:pat` in Rust 1.53.0 to include `|`.
+use something like `$($_:pat)|+`. 
 
-Instead, we will make that change as part of Rust 2021.
+Because this would potentially break existing macros, the meaning of `:pat` did 
+not change in Rust 1.53.0 to include `|`. Instead, that change happens in Rust 2021. 
 In the new edition, the `:pat` fragment specifier *will* match `A | B`.
 
-Since there are times that one still wishes to match a single pattern
-variant without `|`, the fragment specified `:pat_param` has been added
-to retain the older behavior.
-The name refers to its main use case: a pattern in a closure parameter.
+`$_:pat` fragments in Rust 2021 cannot be followed by an explicit `|`. Since there are times 
+that one still wishes to match pattern fragments followed by a `|`, the fragment specified `:pat_param` 
+has been added to retain the older behavior.
+
+It's important to remember that editions are _per crate_, so the only relevant edition is the edition
+of the crate where the macro is defined. The edition of the crate where the macro is used does not 
+change how the macro works.
+
+## Migration to Rust 2021
+
+A lint, `rust_2021_incompatible_or_patterns`, gets triggered whenever there is a use `$:_pat` which
+will change meaning in Rust 2021. 
+
+You can automatically migrate your code to be Rust 2021 Edition compatible or ensure it is already compatible by
+running:
+
+```sh
+cargo fix --edition
+```
+
+If you have a macro which relies on `$_:pat` not matching the top level use of `|` in patterns, 
+you'll need to change each occurrence of `$_:pat` to `$_:pat_param`.
+
+For example:
+
+```rust
+macro_rules! my_macro { 
+       ($x:pat | $y:pat) => {
+               // TODO: implementation
+       } 
+}
+
+// This macro works in Rust 2018 since `$x:pat` does not match against `|`:
+my_macro!(1 | 2);
+
+// In Rust 2021 however, the `$_:pat` fragment matches `|` and is not allowed
+// to be followed by a `|`. To make sure this macro still works in Rust 2021
+// change the macro to the following:
+macro_rules! my_macro { 
+       ($x:pat_param | $y:pat) => { // <- this line is different
+               // TODO: implementation
+       } 
+}
+```
\ No newline at end of file