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

macros: metavariables in tt fragments can hang #35450

Closed
jseyfried opened this issue Aug 7, 2016 · 2 comments
Closed

macros: metavariables in tt fragments can hang #35450

jseyfried opened this issue Aug 7, 2016 · 2 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)

Comments

@jseyfried
Copy link
Contributor

jseyfried commented Aug 7, 2016

@durka reported this in #34925 (comment).

macro_rules! m { ($t:tt) => { $t } }
m!($t); //< This expansion hangs.
@durka
Copy link
Contributor

durka commented Aug 7, 2016

Oh huh, so you didn't even need a nested macro.

@jseyfried jseyfried changed the title macros: Nested macro_rules! can hang macros: metavariables in tt fragments can hang Aug 7, 2016
@jseyfried
Copy link
Contributor Author

@durka Good point, updated the title.

@Aatch Aatch added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Aug 8, 2016
bors added a commit that referenced this issue Aug 14, 2016
macros: Make metavariables hygienic

This PR makes metavariables hygienic. For example, consider:
```rust
macro_rules! foo {
    ($x:tt) => { // Suppose that this token tree argument is always a metavariable.
        macro_rules! bar { ($x:expr, $y:expr) => { ($x, $y) } }
    }
}

fn main() {
    foo!($z); // This currently compiles.
    foo!($y); // This is an error today but compiles after this PR.
}
```
Today, the `macro_rules! bar { ... }` definition is only valid when the metavariable passed to `foo` is not `$y` (since it unhygienically conflicts with the `$y` in the definition of `bar`) or `$x` (c.f. #35450).

After this PR, the definition of `bar` is always valid (and `bar!(a, b)` always expands to `(a, b)` as expected).

This can break code that was allowed in #34925 (landed two weeks ago). For example,
```rust
macro_rules! outer {
    ($t:tt) => {
        macro_rules! inner { ($i:item) => { $t } }
    }
}

outer!($i); // This `$i` should not interact with the `$i` in the definition of `inner!`.
inner!(fn main() {}); // After this PR, this is an error ("unknown macro variable `i`").
```

Due to the severe limitations on nested `macro_rules!` before #34925, this is not a breaking change for stable/beta.

Fixes #35450.

r? @nrc
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, ..)
Projects
None yet
Development

No branches or pull requests

3 participants