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

Multiple bindings of the same metavariable in a macro rule aren't detected until matching. #57593

Closed
alercah opened this issue Jan 14, 2019 · 19 comments · Fixed by #57617
Closed
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug.

Comments

@alercah
Copy link
Contributor

alercah commented Jan 14, 2019

The following macro definition compiles:

macro_rules! bad {
  ($a:expr, $a:expr) => {}
}

Any attempt to match against this macro will result in an error, because the metavariable cannot be bound twice. There is no reason for the compiler to accept this definition as a result, since it always represents a bug, except for backwards compatibility. It should be fixed, either by assuring it won't break the ecosystem or by deprecating the behaviour and denying it the next edition.

@alercah
Copy link
Contributor Author

alercah commented Jan 14, 2019

Example:

macro_rules! ex {
    ($a:expr, $a:expr) => { };
}

fn main() {
    //ex!(1, 2);
}

This compiles fine. But uncommenting the invocation gives an error "duplicated bind name: 'a'". See https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=5990e9c7a1553622afbe0a7fa929d195.

@Centril Centril added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. labels Jan 14, 2019
@Centril
Copy link
Contributor

Centril commented Jan 14, 2019

cc @petrochenkov @rust-lang/lang

I'm not sure if this is by design or not, but it seems like a bug to me so I've marked it as such.

@petrochenkov
Copy link
Contributor

Probably an accidental omission.
(Disclaimer: I never touched the code doing MBE matching and transcription.)

@Centril
Copy link
Contributor

Centril commented Jan 14, 2019

@petrochenkov do you know who to cc by any chance?

@petrochenkov
Copy link
Contributor

do who to cc by any chance?

Spirits of ancestors at this point.

@mark-i-m could be familiar with that code though after implementing ?.

@cramertj
Copy link
Member

Worth noting that if we fix this it needs a crater run, since this would cause previously-compile-able-but-unusable macro_rules variants to stop compiling, e.g.:

macro_rules! my_macro {
    (one_arg $e:expr) => { ... },
    (two_arg $e:expr, $e:expr) => { ... },
}

my_macro!(one_arg, 5);

This would all work fine, so long as no one was testing the two_arg case.

@nikomatsakis
Copy link
Contributor

My impression is that this is an oversight. We could fix it, or we could just add a lint. The latter seems like a good starting point and is what I personally would do.

@mark-i-m
Copy link
Member

I would prefer to fix it over an edition boundary and warn for now.

@mark-i-m
Copy link
Member

I opened #57617, for the technical parts, but we need to sort out policy before I can finish it.

@Centril
Copy link
Contributor

Centril commented Jan 15, 2019

Let's do a crater run before setting out any policy. I think this is clearly a bug tho and thus an edition boundary seems excessive.

@alercah
Copy link
Contributor Author

alercah commented Jan 15, 2019

Waiting for an edition boundary has no value if the goal is to eventually make it deny-by-default across all editions.

@mark-i-m
Copy link
Member

No I meant that we error only in the new edition. I agree that we should do a crater run first, but I expect this to be cause a bunch of breakage.

@mark-i-m
Copy link
Member

I will try to fix up my PR later do we can do a crater run

@cramertj
Copy link
Member

What's the purpose of introducing it as an error rather than a deny-by-default lint?

@Centril
Copy link
Contributor

Centril commented Jan 15, 2019

Let's not speculate about what to do without facts... :)

@mark-i-m
Copy link
Member

Crater run is done #57617 (comment)

@mark-i-m
Copy link
Member

1 regression from crates.io and two more from rust's test suite.

@Centril
Copy link
Contributor

Centril commented Jan 17, 2019

OK we definitely don't need to use an edition boundary for 1 regression... 1-2 release cycle should be enough imo.

@mark-i-m
Copy link
Member

Cross-posting from the PR: I have implemented a future incompatibility lint for this with the goal of later turning it into a hard-error. What's next?

bors added a commit that referenced this issue Feb 9, 2019
…nkov

Error on duplicate matcher bindings

fix  #57593

This should not be merged without a crater run and maybe an FCP. Discussion is ongoing at  #57593.

TODO:
- [x] write tests
- [x] crater run
- [x] ~maybe need edition gating?~ not for 1 regression /centril

r? @petrochenkov
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

Successfully merging a pull request may close this issue.

6 participants