macro_rules! and empty :vis metavariables #71422
Labels
A-macros
Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
C-bug
Category: This is a bug.
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
Hi.
I founds some bugs, did a research, and created a repository with reproducible examples, README, and instructions. Here is the content of README, and the whole repo is attached as zip archive. Code is highly documented, so please take a look. Code snippets and rust-playground are mostly useless, because we'are dealing with proc_macro multi-crate builds.
Issues with macros and
:vis
meta-variableI did a lot of experiments, and I think I found three issues at once:
Empty :vis meta-variable
According to the documentation,
:vis
entity inmacro_rules!
should match empty visibility modifier:vis:
a possibly empty Visibility qualifierWhile this is the case when visibility modifier is followed by some more stuff, it fails on its own:
Followed by stuff:
Even though, adding ident-only branch still matches the first one (with
:vis
):Live rust code of these examples can be found in
./mac/src/q.rs
.Forwarding empty :vis meta-variable
When rustc forwards empty
:vis
meta-variable, it creates an emptyproc_macro::TokenTree::Group
which has no delimiter (proc_macro::Delimiter::None
aka Ø) nor inner stream content (emptyproc_macro::TokenStream
). WhileNone
delimiters is a documented feature (quoted) "important to preserve operator priorities", they "may not survive roundtrip of a token stream through a string".That leads to a workaround, but at the cost of losing context and spans of tokens:
Live rust code using this workaround can be found in
./usage/src/main.rs
(at the bottom) and./mac/src/lib.rs
(turn theUSE_ROUNDTRIP
switch on).Also,
quote!
macro does not produce empty groups like that, so it is higly inconsistent behavior.Unlike
None
delimiter, completely empty group is not documented as a useful feature.Parsing empty group with syn crate
Syn crate is somewhat inconsistent when it comes to parsing empty TokenTree Group.
Steps to reproduce:
mac_with_ident!(bar);
line in./usage/src/with_ident.rs
by commenting out/removing#[cfg!(none)]
attribute.USE_ROUNDTRIP
switch in proc macro.As can be seen from the error message
TAG_B: Error("unexpected token")
,syn::parse2
has no problems parsingsyn::Visibility
out of the ParseStream with single empty group, but it fails to "complete" parsing becauseParseBuffer
is not considered empty (it sees some "tokens" left in the buffer).Proposal:
Rustc macro matching
Fix rustc macro matching subsystem to accept calls without arguments (e.g.
q!()
) as matching arms with single:vis
meta-variable (e.g.macro_rules! q { ($v:vis) => {} }
)Rust macro expansion
Fix rustc macro expansion subsystem to stop forwarding empty
vis
tokens as an empty groups.Syn parser robustness
Regardless of fixed in rustc, syn/proc_macro2 crates should handle those empty groups gracefully AND uniformly.
Probably, skip those blank groups altogether. It's no good that they handle a "blank group" and a "blank group which is followed by stuff" cases differently.
Meta
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: