Skip to content

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

New issue

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

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

Already on GitHub? # to your account

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.

# for free to join this conversation on GitHub. Already have an account? # 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