Closed
Description
As part of the |
patterns work (tracking issue), we plan to change the meaning of the $x:pat
matcher in macros within the 2021 Edition. The current plan of record is:
- The
pat2015
matcher will match legacy patterns, which exclude the|
character. - The
pat2021
matcher will match new patterns, which include the|
character. - The
pat
matcher will be equivalent topat2021
from Rust 2021 forward, and equivalent topat2015
on older editions, since past crater runs (e.g., 1 and 2) found significant and complex breakage from just changingpat
topat2021
uniformly.
The goal of this issue is to issue a useful lint that suggests that converting $x:pat
to $x:pat2015
if converting to Rust 2021 could cause breakage. We don't want to do this for all $x:pat
usages, however, because the vast majority would benefit from being $x:pat2021
.
Examples where lint should trigger
Here is an example of a macro that we DO want to convert (source):
#[macro_export]
macro_rules! match_any {
( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
match $expr {
$(
$( $pat => $expr_arm, )+
)+
}
};
}
Here is another example (source):
/// Helper macro for declaring byte-handler functions with correlating constants.
/// This becomes handy due to a lookup table present below.
macro_rules! define_handlers {
{ $(const $static_name:ident: $name:ident |$tok:pat, $byte:pat| $code:block)* } => {
$(
fn $name($tok: &mut Tokenizer, $byte: u8) -> Result<Token> $code
const $static_name: fn(&mut Tokenizer, u8) -> Result<Token> = $name;
)*
}
}
Metadata
Metadata
Assignees
Labels
Call for participation: Help is requested to fix this issue.Call for participation: Medium difficulty. Experience needed to fix: Intermediate.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.`#![feature(or_patterns)]`Relevant to the compiler team, which will review and decide on the PR/issue.
Activity
nikomatsakis commentedon Mar 20, 2021
Mentoring instructions
There is some existing logic in macros to try and detect cases where a matcher is followed by an illegal character. I think we can build on this logic easily enough. Here is an example function I found when ripgreping around:
rust/compiler/rustc_expand/src/mbe/macro_rules.rs
Lines 853 to 871 in 3ad1e4d
I think these three lines are roughly where we want to make changes:
rust/compiler/rustc_expand/src/mbe/macro_rules.rs
Lines 964 to 967 in 3ad1e4d
What this code is currently doing is checking if you have something like
$x:expr Y
thatY
is a character allowed to followexpr
. The idea was to future-proof against extensions to whatexpr
could match by accepting onlyY
characters that already separate expressions, like,
or;
. Unfortunately, for$x:pat Y
we accepted aY
or|
, which is the whole problem here. So what we want to do is to add an extra case here that says "if this is apat
meta variable, and thenext_token
is `|, then issue a lint warning."nikomatsakis commentedon Mar 20, 2021
There is a Zulip thread on or patterns here:
https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/or.20patterns
0xPoe commentedon Mar 20, 2021
@rustbot claim
0xPoe commentedon Mar 20, 2021
I would like to try this.
nikomatsakis commentedon Mar 22, 2021
@hi-rustin great!
m-ou-se commentedon Mar 22, 2021
I changed the difficulty label from easy to medium, since it's not easy to generate a lint at that place in the rustc code.
m-ou-se commentedon Mar 22, 2021
Producing a lint there with
sess.buffer_lint()
'works' for warn-by-default lints. But when making it an allow-by-default lint (as this should be), it triggers an internal compiler error.11 remaining items