Skip to content

No macro hygiene for items #19700

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

Closed
maxsnew opened this issue Dec 10, 2014 · 5 comments
Closed

No macro hygiene for items #19700

maxsnew opened this issue Dec 10, 2014 · 5 comments
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)

Comments

@maxsnew
Copy link

maxsnew commented Dec 10, 2014

Uses of identifiers in a macro expansion refer to identifiers in the macro use-site and not the macro-definition site, effectively giving macros dynamic scope.

Minimal example:

#![feature(macro_rules)]

fn foo() -> bool {
    true
}

macro_rules! bar(
    () => (foo())
)

#[cfg(test)]
mod test {
    fn foo() -> bool {
        false
    }
    #[test]
    fn test() {
        assert!(bar!());
    }
}

Testing this program will result in a test failure because when bar!() expands to foo() the foo is the foo in the test submodule, whereas it should refer to the foo in the top-level module where bar! was defined.

This paper is a good resource for implementing this: http://www.cs.utah.edu/plt/publications/macromod.pdf

@Manishearth
Copy link
Member

Actually, identifiers are protected by hygiene (and will not capture any scope unless the identifier is passed down), but function identifiers aren't.

Macros only deal with token trees -- I'm not sure how to manipulate tts to generically refer to a function defined in another crate that may or may not have a different name.

@maxsnew
Copy link
Author

maxsnew commented Dec 10, 2014

Only let-bound identifiers are safe. Functions, imports, and statics all have this same issue. The following still fails, though not because of functions:

#![feature(macro_rules)]

static BLAHBLAH: bool = true;
macro_rules! bar(
    () => ({
        BLAHBLAH
    })
)

#[cfg(test)]
mod test {
    static BLAHBLAH: bool = false;

    #[test]
    fn test() {
        assert!(bar!());
    }
}

@kmcallister kmcallister added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Jan 17, 2015
@kmcallister kmcallister changed the title Macros are Not Lexical No macro hygiene for items Jan 17, 2015
@kmcallister
Copy link
Contributor

This is unfortunate, but it's the documented behavior of macro_rules! 1.0 and there is no time to fix it for Rust 1.0. Item/crate hygiene is one of the top priorities for macros two point oh.

See #22462 for a specific manifestation of this problem that I think we can mitigate in time.

@maxsnew
Copy link
Author

maxsnew commented Mar 3, 2015

I don't understand why this issue is closed. You're acknowledging it as something that should be fixed so shouldn't it be left open?

@kmcallister
Copy link
Contributor

This aspect of macro_rules! can't be fixed in a backwards-compatible way, and it can't be fixed in time for Rust 1.0, when the backwards-compatibility guarantees kick in.

We will at some point introduce a new macro system, first in Rust nightlies, then in some stable Rust 1.x. This would happen through the RFC process. It would coexist with the current macro_rules! until Rust 2.0. The item hygiene issue will not be overlooked by the people designing the new macro system. It is probably the top consideration.

Until there's a full RFC, we can discuss this further on rust-lang/rfcs#440.

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