Skip to content

Commit 006b8b5

Browse files
committed
Add migration details to or-patterns guide
1 parent 288f611 commit 006b8b5

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

src/rust-2021/or-patterns-macro-rules.md

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
## Summary
44

5-
- `$_:pat` in `macro_rules` now matches `|` too: e.g. `A | B`.
6-
- `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`.
7-
- `$_:pat_param` is available in all editions.
5+
- How patterns work in `macro_rules` macros changes slightly:
6+
- `$_:pat` in `macro_rules` now matches usage of `|` too: e.g. `A | B`.
7+
- The new `$_:pat_param` behaves like `$_:pat` did before; it does not match (top level) `|`.
8+
- `$_:pat_param` is available in all editions.
89

910
## Details
1011

@@ -15,18 +16,47 @@ Since this was simply not allowed before, this is not a breaking change.
1516

1617
However, this change also affects [`macro_rules` macros](https://doc.rust-lang.org/stable/reference/macros-by-example.html).
1718
Such macros can accept patterns using the `:pat` fragment specifier.
18-
Currently, `:pat` does *not* match `|`, since before Rust 1.53,
19+
Currently, `:pat` does *not* match top level `|`, since before Rust 1.53,
1920
not all patterns (at all nested levels) could contain a `|`.
2021
Macros that accept patterns like `A | B`,
2122
such as [`matches!()`](https://doc.rust-lang.org/1.51.0/std/macro.matches.html)
22-
use something like `$($_:pat)|+`.
23-
Because we don't want to break any existing macros,
24-
we did *not* change the meaning of `:pat` in Rust 1.53.0 to include `|`.
23+
use something like `$($_:pat)|+`.
2524

26-
Instead, we will make that change as part of Rust 2021.
25+
Because this would potentially break existing macros, the meaning of `:pat` did
26+
not change in Rust 1.53.0 to include `|`. Instead, that change happens in Rust 2021.
2727
In the new edition, the `:pat` fragment specifier *will* match `A | B`.
2828

29-
Since there are times that one still wishes to match a single pattern
30-
variant without `|`, the fragment specified `:pat_param` has been added
31-
to retain the older behavior.
32-
The name refers to its main use case: a pattern in a closure parameter.
29+
`$_:pat` fragments in Rust 2021 cannot be followed by an explicit `|`. Since there are times
30+
that one still wishes to match pattern fragments followed by a `|`, the fragment specified `:pat_param`
31+
has been added to retain the older behavior.
32+
33+
It's important to remember that editions are _per crate_, so the only relevant edition is the edition
34+
of the crate where the macro is defined. The edition of the crate where the macro is used does not
35+
change how the macro works.
36+
37+
## Migration to Rust 2021
38+
39+
If you have a macro which relies on `$_:pat` not matching the top level use of `|` in patterns,
40+
you'll need to change each occurrence of `$_:pat` to `$_:pat_param`.
41+
42+
For example:
43+
44+
```rust
45+
macro_rules! my_macro {
46+
($x:pat | $y:pat) => {
47+
// TODO: implementation
48+
}
49+
}
50+
51+
// This macro works in Rust 2018 since `$x:pat` does not match against `|`:
52+
my_macro!(1 | 2);
53+
54+
// In Rust 2021 however, the `$_:pat` fragment matches `|` and is not allowed
55+
// to be followed by a `|`. To make sure this macro still works in Rust 2021
56+
// change the macro to the following:
57+
macro_rules! my_macro {
58+
($x:pat_param | $y:pat) => { // <- this line is different
59+
// TODO: implementation
60+
}
61+
}
62+
```

0 commit comments

Comments
 (0)