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

No macro hygiene for items #19700

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

Comments

Projects
None yet
3 participants
@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

This comment has been minimized.

Copy link
Member

Manishearth commented Dec 10, 2014

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

This comment has been minimized.

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 changed the title Macros are Not Lexical No macro hygiene for items Jan 17, 2015

@kmcallister

This comment has been minimized.

Copy link
Contributor

kmcallister commented Mar 3, 2015

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.

@kmcallister kmcallister closed this Mar 3, 2015

@maxsnew

This comment has been minimized.

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

This comment has been minimized.

Copy link
Contributor

kmcallister commented Mar 3, 2015

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
You can’t perform that action at this time.