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 hygiene bug #32922

Closed
jseyfried opened this issue Apr 13, 2016 · 12 comments · Fixed by #32923
Closed

Macro hygiene bug #32922

jseyfried opened this issue Apr 13, 2016 · 12 comments · Fixed by #32923

Comments

@jseyfried
Copy link
Contributor

The following should print 1, but it currently prints 0:

fn main() {
    let x = 0;
    macro_rules! foo { () => {
        let x = 1;
        macro_rules! bar { () => {x} }
        println!("{}", bar!());
    }}

    foo! {};
}

For comparison, the following correctly prints 1:

fn main() {
    let x = 0;
    macro_rules! foo { () => {{ //< note the added brace here
        let x = 1;
        macro_rules! bar { () => {x} }
        println!("{}", bar!());
    }}}

    foo! {};
}
@jseyfried
Copy link
Contributor Author

cc @nrc

@jseyfried
Copy link
Contributor Author

Another example -- the following should print 1 but currently does not compile:

macro_rules! foo { () => {
    let x = 1;
    macro_rules! bar { () => {x} }
    println!("{}", bar!());
}}

fn main() {
    foo! {};
}

Either adding another pair of braces (as in the first initial comment) or manually expanding the macro allows this example to compile.

jseyfried added a commit to jseyfried/rust that referenced this issue Apr 13, 2016
@durka
Copy link
Contributor

durka commented Apr 13, 2016

This is probably a special case of hygiene not really working at all in multi-statement macros, #31856.

@jseyfried
Copy link
Contributor Author

@durka indeed it is. That issue is also fixed by #32923.

@durka
Copy link
Contributor

durka commented Apr 14, 2016

Amazing, thanks! (Should we check crater for breakage, though?)

@jseyfried
Copy link
Contributor Author

I think it's unlikely that there will be breakage, but it would probably be a good idea to check anyway, especially since silent changes in behavior are scary.

@durka
Copy link
Contributor

durka commented Apr 14, 2016

Well crater doesn't catch those, so we just have to hope that nobody was actually using multi-statement macros...

@jseyfried
Copy link
Contributor Author

True, but if there's no breakage I believe that's pretty strong evidence that there won't be any behavior changes since I would think breakage (either due to there not being a shadowing binding in the macro expansion or due to the shadowing binding being of the wrong type) would be much more likely than a behavior change (in which there would need to be a shadowing binding of the same type).

@jseyfried
Copy link
Contributor Author

Also, does crater run tests?

@bluss
Copy link
Member

bluss commented Apr 14, 2016

Right, crater does not normally run tests. So macros not used/expanded in a crate somewhere are entirely unexercised by crater.

@durka
Copy link
Contributor

durka commented Apr 14, 2016

Does it build the tests? If not perhaps it builds bins, and we could "test" macro crates that way?

@durka
Copy link
Contributor

durka commented Apr 14, 2016

It seems that crater simply runs cargo build. As an experiment I just hacked up this crate so the integration tests are configured as no-op bins, such that cargo build fails if the tests fail to build. It's pretty ugly though and is obviously opt-in.

Manishearth added a commit to Manishearth/rust that referenced this issue Apr 15, 2016
Fix macro hygiene bug

This fixes rust-lang#32922 (EDIT: and fixes rust-lang#31856), macro hygiene bugs.
It is a [breaking-change]. For example, the following would break:
```rust
fn main() {
    let x = true;
    macro_rules! foo { () => {
        let x = 0;
        macro_rules! bar { () => {x} }
        let _: bool = bar!();
        //^ `bar!()` used to resolve the first `x` (a bool),
        //| but will now resolve to the second x (an i32).
    }}
    foo! {};
}
```

r? @nrc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants