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 expanded pretty printed code doesn't follow macro hygiene rules #58031

Closed
fyrchik opened this issue Jan 31, 2019 · 4 comments
Closed

Macro expanded pretty printed code doesn't follow macro hygiene rules #58031

fyrchik opened this issue Jan 31, 2019 · 4 comments
Labels
A-pretty Area: Pretty printing (including `-Z unpretty`) C-bug Category: This is a bug.

Comments

@fyrchik
Copy link
Contributor

fyrchik commented Jan 31, 2019

Hello. I have just started studying rust (and macros), so may not understand fully how it works.

macro_rules! new_bind {
    ($t:ident, $f:expr) => {
        let t = $f;
        println!("3. t = {}", t);
    };
}

macro_rules! existing_ident {
    ($t:ident, $f:expr) => {
        $t = $f;
        println!("1. t = {}", $t);
    };
}

fn main() {
    let mut t = 0;

    existing_ident!(t, 1);
    println!("2. t = {}", t);

    new_bind!(t, 2);
    println!("4. t = {}", t);
}

This code produces following ouptut:

1. t = 1
2. t = 1
3. t = 2
4. t = 1

While I expect following output (also looking at cargo expand results), because new_bind! macro introduces new let binding in the same scope:

1. t = 1
2. t = 1
3. t = 2
4. t = 2

I have found similar issues, but am not sure if they are the same.

#32922
#31856

@ExpHP
Copy link
Contributor

ExpHP commented Jan 31, 2019

This is macro hygiene. It's a feature.

@estebank
Copy link
Contributor

This is actually a bug in cargo expand, not in the macro hygiene. The compiler expands to something closer to:

fn main() {
    let mut t = 0;

    t = 1;
    println!("1. t = {}", t);

    println!("2. t = {}", t);

    {
        let t = 2;
        println!("3. t = {}", t);
    }  // the `t` binding inside this scope goes away after the block goes away and the outer `t` is not accessible due to shadowing
    println!("4. t = {}", t); // this `t` is the one from earlier
}

@estebank estebank added A-pretty Area: Pretty printing (including `-Z unpretty`) C-bug Category: This is a bug. labels Jan 31, 2019
@estebank estebank changed the title possible bug in macro expansion Macro expanded pretty printed code doesn't follow macro hygiene rules Jan 31, 2019
@ExpHP
Copy link
Contributor

ExpHP commented Jan 31, 2019

Well, wrapping it in a block gives a variety of wrong impressions about scope, drop order, and how existing_ident! works. I'd say it's much closer to

fn main() {
    let mut t = 0;

    t = 1;
    println!("1. t = {}", t);

    println!("2. t = {}", t);

    let t_0 = 2;
    println!("3. t = {}", t_0);

    println!("4. t = {}", t);
}

@Mark-Simulacrum
Copy link
Member

Closing as dupe of #13573.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-pretty Area: Pretty printing (including `-Z unpretty`) C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

4 participants