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

Nested macro invocation doesn't follow proper scoping rules #9323

Closed
lilyball opened this issue Sep 19, 2013 · 10 comments
Closed

Nested macro invocation doesn't follow proper scoping rules #9323

lilyball opened this issue Sep 19, 2013 · 10 comments
Labels
A-syntaxext Area: Syntax extensions C-feature-request Category: A feature request, i.e: not implemented / a PR.

Comments

@lilyball
Copy link
Contributor

When one macro invokes another macro, it always looks up the nested macro from the point of the outer invocation, instead of from the point of the macro definition. I don't know if this is intentional.

Example:

fn main() {
    macro_rules! foo(
        () => (println!("outer"))
    );
    {
        macro_rules! bar(
            () => (foo!())
        );
        {
            macro_rules! foo(
                () => (println!("inner"))
            );
            bar!()
        }
    }
}

If these were functions, it would print outer, but instead it prints inner.

@huonw
Copy link
Member

huonw commented Jul 13, 2014

cc @jbclements

@jbclements
Copy link
Contributor

Yes, this is definitely a bug. The bar! macro should expand into a use of the outer foo! macro, not the inner one; this otherwise subverts the definition of the bar! macro completely. Put differently, it violates the macro-writer's bill of rights (yes, that's a thing. though I may be mis-using the term).

The solution? Hygiene for macro names. One thing at a time...

@huonw , thanks for the cc: !

@frewsxcv
Copy link
Member

@kballard Are you able to confirm if this is still valid with the latest Rust? Your original code block doesn't compile currently.

@lilyball
Copy link
Contributor Author

@frewsxcv It's still broken. I just updated the original code block with something that compiles.

@Ryman
Copy link
Contributor

Ryman commented Jun 10, 2015

I think this example is related:

macro_rules! foo {
    ($v:ident) => (
        let $v = 3;
        println!("{}", $v); // If you comment this then it's fine.
    );
}

fn main() {
    foo!(x);
    println!("{}", x);
}

@jbclements
Copy link
Contributor

@Ryman No... I think that's a different problem. Can you file a separate issue for that, and send me mail when you're done? (BTW, be sure to include the expected and actual behavior when you do.)

@Ryman
Copy link
Contributor

Ryman commented Jun 11, 2015

@jbclements Opened #26223

@steveklabnik
Copy link
Member

steveklabnik commented Jan 3, 2017

Triage: same error today, in that it prints inner.

@Mark-Simulacrum Mark-Simulacrum added the C-feature-request Category: A feature request, i.e: not implemented / a PR. label Jul 19, 2017
@steveklabnik
Copy link
Member

Triage: macro_rules is not being worked on anymore, with macro as its replacement. Given that there's been no substantial comments since 2015, and it still reproduced in 2017, I don't believe this will be changed. Closing.

@petrochenkov
Copy link
Contributor

petrochenkov commented Sep 24, 2018

This is expected behavior for macro_rules macros which are hygienic only for local variables and labels.

Macros 2.0 (macro) change this behavior and the example prints "outer".

#![feature(decl_macro)]

fn main() {
    macro foo{
        () => (println!("outer"))
    }
    {
        macro bar{
            () => (foo!())
        }
        {
            macro foo{
                () => (println!("inner"))
            }
            bar!()
        }
    }
}

Declarative macros 2.0 are deeply unstable and macro_rules is still the primary declarative macro system in Rust, so they are worked on in terms of both bugs and occasionally extensions.

flip1995 pushed a commit to flip1995/rust that referenced this issue Aug 11, 2022
Rustup

r? `@ghost`

changelog: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-syntaxext Area: Syntax extensions C-feature-request Category: A feature request, i.e: not implemented / a PR.
Projects
None yet
Development

No branches or pull requests

8 participants