Skip to content

Identity macro 'launders' hygiene information #59011

Description

@pierzchalski

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?

Activity

  1. pierzchalski commented on Mar 8, 2019

    @pierzchalski
    ContributorAuthor

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

  2. alexreg commented on Mar 8, 2019

    @alexreg
    Contributor

    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?).

  3. self-assigned this
    on Mar 8, 2019
  4. petrochenkov commented on Mar 14, 2020

    @petrochenkov
    Contributor

    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

Metadata

Metadata

Assignees

Labels

A-decl-macros-2-0Area: Declarative macros 2.0 (#39412)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions