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

$crate unexpectedly disintegrates depending on unrelated macro invocations #57089

Closed
dtolnay opened this issue Dec 24, 2018 · 1 comment · Fixed by #57155
Closed

$crate unexpectedly disintegrates depending on unrelated macro invocations #57089

dtolnay opened this issue Dec 24, 2018 · 1 comment · Fixed by #57155
Assignees
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug.

Comments

@dtolnay
Copy link
Member

dtolnay commented Dec 24, 2018

I have proc macros mac! which is function-like and #[attr] which is an attribute. Both of them simply emit their input unchanged (input.into_iter().collect()).

I have an invocation of both macros from another crate which passes tokens containing $crate. In the code below, everything is working as expected and both macros receive Ident { ident: "$crate" } in their input.

Now for the broken bit: I observed some spooky action at a distance in which changing the behavior of mac! affects the input of the totally unrelated invocation of #[attr]. The input of #[attr] decomposes into Punct { ch: '$' } + Ident { ident: "crate" } which rustc refuses to parse down the line.

  • Either we need to find out what is causing $crate to disintegrate into $ + crate and stop that from happening (preferred),
  • Or the parser needs to accept an appropriately spanned $ + crate where it appears in procedural macro output.

repro_macros/src/lib.rs

extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro]
pub fn mac(input: TokenStream) -> TokenStream {
    println!("MAC INPUT: {:#?}", input);

    // Change this to `false` to observe the spooky effect on the input of #[attr].
    if true {
        input.into_iter().collect()
    } else {
        TokenStream::new()
    }
}

#[proc_macro_attribute]
pub fn attr(_args: TokenStream, input: TokenStream) -> TokenStream {
    println!("ATTR INPUT: {:#?}", input);
    input.into_iter().collect()
}

repro/src/lib.rs

const UNIT: () = ();

macro_rules! m {
    () => {
        repro_macro::mac! {
            pub fn f() {
                $crate::UNIT
            }
        }

        #[repro_macro::attr]
        pub fn g() {
            $crate::UNIT
        }
    };
}

m!();

Mentioning @petrochenkov since you worked on #56647.
Mentioning @alexcrichton.

rustc 1.33.0-nightly (2d3e909 2018-12-22)

@dtolnay dtolnay added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. labels Dec 24, 2018
@petrochenkov
Copy link
Contributor

Fixed in #57155

bors added a commit that referenced this issue Dec 28, 2018
Resolve `$crate`s for pretty-printing at more appropriate time

Doing it in `BuildReducedGraphVisitor` wasn't a good idea, identifiers wasn't actually visited half of the time.
As a result some `$crate`s weren't resolved and were therefore pretty-printed as `$crate` literally, which turns into two tokens during re-parsing of the pretty-printed text.

Now we are visiting and resolving `$crate` identifiers in an item right before sending that item to a proc macro attribute or derive.

Fixes #57089
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, ..) C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants