Skip to content

Macros 2.0: #[cfg_attr] makes .to_string() and TokenStream disagree #48644

Closed
@alexcrichton

Description

@alexcrichton

I ran across a very curious case today... Given this procedural macro:

#![crate_type = "proc-macro"]
#![feature(proc_macro)]

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_derive(Foo, attributes(foo))]
pub fn foo(input: TokenStream) -> TokenStream {
    println!("{}", input.to_string());
    print_tts(input, 0);

    TokenStream::empty()
}

fn print_tts(input: TokenStream, tab: usize) {
    let mut t = String::new();
    for _ in 0..tab {
        t.push_str("  ");
    }
    for token in input {
        match token.kind {
            proc_macro::TokenNode::Group(d, others) => {
                println!("{}{:?}", t, d);
                print_tts(others.into(), tab + 1);
            }
            s => println!("{}{:?}", t, s),
        }
    }
}

and this expansion:

#![crate_type = "rlib"]
#![feature(proc_macro)]

#[macro_use]
extern crate foo;

#[derive(Foo)]
pub struct MyStructc {
    #[cfg_attr(my_cfg, foo)]
    _a: i32,
}

when compiled I get:

$ rustc +nightly foo.rs && rustc +nightly bar.rs -L .
pub struct MyStructc {
    _a: i32,
}
Term(Term(pub))
Term(Term(struct))
Term(Term(MyStructc))
Brace
  Op('#', Alone)
  Bracket
    Term(Term(cfg_attr))
    Parenthesis
      Term(Term(my_cfg))
      Op(',', Alone)
      Term(Term(foo))
  Term(Term(_a))
  Op(':', Alone)
  Term(Term(i32))
Op(',', Alone)

which is quite curious!

The to_string() representation has the field present (even though the --cfg isn't supplied) and the token stream has the actual #[cfg_attr] there.

I was actually expecting neither outcome to happen (how naive of me!) in terms of #[cfg] processing typically happening before custom derives, but maybe that's not possible? -- er, just wrong thinking here

cc @dtolnay
cc @jseyfried
cc @nrc

Metadata

Metadata

Assignees

No one assigned

    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