Skip to content
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

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
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants