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

Identity macro 'launders' hygiene information #59011

Closed
pierzchalski opened this issue Mar 8, 2019 · 3 comments
Closed

Identity macro 'launders' hygiene information #59011

pierzchalski opened this issue Mar 8, 2019 · 3 comments
Assignees
Labels
A-macros-2.0 Area: Declarative macros 2.0 (#39412)

Comments

@pierzchalski
Copy link
Contributor

Consider this hygiene demonstration (playground):

#![feature(decl_macro)]

macro x() {
    println!("x");
}

macro y() {
    x!(); // This `x` identifier is in a fresh hygiene scope within `y`,
    macro x() { println!("y"); } // so it resolves to this definition.
}

fn main() {
    y!();
}

This prints "y", as expected.

However, if we 'launder' the definition macro x() using an identity macro (playground):

#![feature(decl_macro)]

macro id($($tt:tt)*) {
    $($tt)*
}

macro x() {
    println!("x");
}

macro y() {
    x!();
    id!(macro x() { println!("y"); }); // What is the scope of this `x`?
}

fn main() {
    y!();
}

We get an error that the invocation of x is ambiguous.

Is this the expected behaviour?

@pierzchalski
Copy link
Contributor Author

Pinging the usual crowd: @alexreg @nrc @petrochenkov @dtolnay

@estebank estebank added the A-macros-2.0 Area: Declarative macros 2.0 (#39412) label Mar 8, 2019
@alexreg
Copy link
Contributor

alexreg commented Mar 8, 2019

I agree, this is strange. I'd expect the hygiene for the inner definition of the macro x to be almost the same in both cases (just an extra expansion mark in the second case?).

@petrochenkov petrochenkov self-assigned this Mar 8, 2019
@petrochenkov
Copy link
Contributor

petrochenkov commented Mar 14, 2020

This works as expected.

Both macro xs are in scope when we are resolving x!().
The first one is in scope too because macros 2.0 provide definition site hygiene (so stuff like this works) and it's in scope at definition point of macro y.

In the first example the inner macro x shadows the outer macro x and everything compiles successfully.

In the second case both macro xs are still in scope, but they hit a restricted shadowing rule, that's unrelated to hygiene, but related to expansion algorithm and ensures that it gives predictable results.
Names materializing later during expansion (like the second macro x) cannot shadow names materializing earlier during expansion (like the first macro x), so we get the "cannot shadow" error aka ambiguity error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros-2.0 Area: Declarative macros 2.0 (#39412)
Projects
None yet
Development

No branches or pull requests

4 participants