Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macro_rules! thinks use is an ident. It isn't. #40569

Closed
sgrif opened this issue Mar 16, 2017 · 6 comments
Closed

macro_rules! thinks use is an ident. It isn't. #40569

sgrif opened this issue Mar 16, 2017 · 6 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug.

Comments

@sgrif
Copy link
Contributor

sgrif commented Mar 16, 2017

This code should fail to compile, giving the same error message as fn use() would give, but it compiles successfully.

macro_rules! foo {
    ($foo:ident) => {}
}

fn main() {
    foo!(use);
}

This code should compile successfully. However, it fails complaining that it can't decide whether use is an ident or not (hint: it isn't). It also shouldn't be trying to match use as an ident because of the semicolon, but that's a broader/deeper issue with macro_rules!

macro_rules! foo {
    ($(use ;)* $foo:ident) => {}
}

fn main() {
    foo!(use ; use ; bar);
}
@petrochenkov
Copy link
Contributor

ident matcher accepts keywords (and also reserved keywords) by design (see very similar issue about self - #27899 (comment) cc @nrc).

@sgrif
Copy link
Contributor Author

sgrif commented Mar 16, 2017

From that issue:

I suppose, ident can be backward compatibly restricted to reject keywords and reserved identifiers with exception of path segment keywords super, self and Self (because you may want to write things like $seg: ident => $seg::foo::bar), but I don't see much benefit from such restriction.

The second case given in this issue is a very concrete benefit from that restriction. 😄

@sgrif
Copy link
Contributor Author

sgrif commented Mar 16, 2017

It looks like repeaters can pretty easily confuse macro_rules! even in more ridiculous cases. e.g.

macro_rules! my_struct {
    ($(#[$meta:meta])* $ident:ident) => {
        $(#[$meta])* struct $ident;
    }
}

my_struct!(#[derive(Debug)] Foo);

causes it to complain that it doesn't know if # is supposed to be an ident or not

@durka
Copy link
Contributor

durka commented Mar 16, 2017

The repetition thing is because macro_rules just doesn't attempt any backtracking. This has been reported before. You need to put a constant token in between (e.g. struct). It's obviously not backwards compatible to change the definition of ident now, I don't know what @petrochenkov was talking about in that quote...

@dtolnay
Copy link
Member

dtolnay commented Mar 16, 2017

One specific common macro that this would break is Serde's forward_to_deserialize_any which accepts "struct" and "enum" as idents.

@Mark-Simulacrum Mark-Simulacrum added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Jun 22, 2017
kennytm added a commit to kennytm/rust that referenced this issue Jul 7, 2017
bors added a commit that referenced this issue Jul 11, 2017
…seyfried

Only match a fragment specifier the if it starts with certain tokens.

When trying to match a fragment specifier, we first predict whether the current token can be matched at all. If it cannot be matched, don't bother to push the Earley item to `bb_eis`. This can fix a lot of issues which otherwise requires full backtracking (#42838).

In this PR the prediction treatment is not done for `:item`, `:stmt` and `:tt`, but it could be expanded in the future.

Fixes #24189.
Fixes #26444.
Fixes #27832.
Fixes #34030.
Fixes #35650.
Fixes #39964.
Fixes the 4th comment in #40569.
Fixes the issue blocking #40984.
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 27, 2017
@petrochenkov
Copy link
Contributor

Closing as works-as-expected and cannot-be-changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

5 participants