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.nikomatsakis commentedon Mar 23, 2021
@m-ou-se good catch, I forgot about that. I suspect this ICE is... simply not necessary. @hi-rustin have you had a chance to do any exploration here?
The other thing is that @m-ou-se pointed out that we probably want to modify the rules for
pat
in 2021 at least, so that we give a hard error if|
is in the follow-set. We can likely do that as part of this PR, but I will wait until we have the PR in hand to worry about it.0xPoe commentedon Mar 23, 2021
I'll give it a try, but at the moment I'm not very familiar with the compiler code and it might be difficult.
Foo(Bar(x) | Baz(x))
" #54883nikomatsakis commentedon Mar 24, 2021
@hi-rustin if it would be helpful, we could schedule some time to chat on Zulip synchronously, presuming our time zones can be made to overlap =) If that would be useful to you, let me know and I'll have contact you via email to schedule a time.
0xPoe commentedon Mar 25, 2021
Thank you for your support! I've written some code that I'll submit later.
0xPoe commentedon Mar 25, 2021
I've created a draft PR, could you please take a look?
cc: #83468
Rollup merge of rust-lang#83468 - hi-rustin:rustin-patch-lint, r=niko…
Auto merge of rust-lang#83468 - hi-rustin:rustin-patch-lint, r=nikoma…