rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.4k stars 12.59k forks source link

Follow token restriction disallows keywords after path fragment specifier (and likely others) #101788

Open jplatte opened 2 years ago

jplatte commented 2 years ago

I just wanted to add match guard support to the as_variant crate I published yesterday, but found that it was impossible without turning the macro into a token muncher (something I'm not familiar enough with and also find rather unappealing).

Basically, I tried this:

macro_rules! as_variant {
    ( $enum:expr, $( $variants:path )|* $( if $guard:expr )? ) => { /* ... */ };
}

and got the error

error: `$variants:path` may be followed by `if`, which is not allowed for `path` fragments
   --> src/lib.rs:120:44
    |
120 |     ( $enum:expr, $( $variants:path )|* $( if $guard:expr )? ) => {
    |                                            ^^ not allowed after `path` fragments
    |
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`

which seems wrong.

Actually after writing most of this report and seeing as and where in the list I found a workaround that's not token munching, I can use pat_param instead of path, but I feel like what I wrote originally should still be allowed.

CohenArthur commented 8 months ago

it seems to me that this is not a bug, as the current (Follow-set ambiguity restrictions)[https://doc.rust-lang.org/reference/macros-by-example.html#follow-set-ambiguity-restrictions] disallow this:

( $enum:expr, $( $variants:path )|* $( if $guard:expr )? ) can match something of the form $expr, $path1 | $path2 if $expr which would indeed trigger the ambiguity restrictions.

the set of restrictions is there to prevent backward compatibility issues as much as possible, so I'm not sure it can be changed easily to allow that pattern

jplatte commented 8 months ago

Right, basically I meant this issue as a feature request to add if and possibly other keywords to the follow-set of path (and maybe ty, apparently those use the same set).