Skip to content

Field attributes lost in proc macro input #68710

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
dtolnay opened this issue Jan 31, 2020 · 1 comment · Fixed by #68737
Closed

Field attributes lost in proc macro input #68710

dtolnay opened this issue Jan 31, 2020 · 1 comment · Fixed by #68737
Assignees
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@dtolnay
Copy link
Member

dtolnay commented Jan 31, 2020

If we have an attribute macro whose input contains attributes on fields of a struct-expression, those attributes all seem to disappear before the macro is invoked.

The following repro compiles successfully if #[repro::repro] is removed, but fails with "error[E0062]: field `field` specified more than once" if the macro is present even though it does nothing.

struct C {
    field: u8,
}

#[repro::repro]
const C: C = C {
    #[cfg(debug_assertions)]
    field: 0,
    #[cfg(not(debug_assertions))]
    field: 1,
};

fn main() {}
extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn repro(_args: TokenStream, input: TokenStream) -> TokenStream {
    println!("{:#?}", input);
    input.into_iter().collect()
}
Here is a script that reproduces the behavior as of rustc 1.42.0-nightly (212b2c7 2020-01-30)
#!/bin/bash

cargo new repro

echo >>repro/Cargo.toml '
[lib]
proc-macro = true
'

echo >repro/src/lib.rs '
extern crate proc_macro;
use proc_macro::TokenStream;

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

echo >repro/src/main.rs '
struct C {
    field: u8,
}
#[repro::repro]
const C: C = C {
    #[cfg(debug_assertions)]
    field: 0,
    #[cfg(not(debug_assertions))]
    field: 1,
};
fn main() {}
'

cargo +nightly check --manifest-path repro/Cargo.toml
Here is the input token stream as received by the proc macro
TokenStream [
    Ident {
        ident: "const",
        span: #0 bytes(0..0),
    },
    Ident {
        ident: "C",
        span: #0 bytes(0..0),
    },
    Punct {
        ch: ':',
        spacing: Alone,
        span: #0 bytes(0..0),
    },
    Ident {
        ident: "C",
        span: #0 bytes(0..0),
    },
    Punct {
        ch: '=',
        spacing: Alone,
        span: #0 bytes(0..0),
    },
    Ident {
        ident: "C",
        span: #0 bytes(0..0),
    },
    Group {
        delimiter: Brace,
        stream: TokenStream [
            Ident {
                ident: "field",
                span: #0 bytes(0..0),
            },
            Punct {
                ch: ':',
                spacing: Alone,
                span: #0 bytes(0..0),
            },
            Literal { lit: Lit { kind: Integer, symbol: "0", suffix: None }, span: Span { lo: BytePos(0), hi: BytePos(0), ctxt: #0 } },
            Punct {
                ch: ',',
                spacing: Alone,
                span: #0 bytes(0..0),
            },
            Ident {
                ident: "field",
                span: #0 bytes(0..0),
            },
            Punct {
                ch: ':',
                spacing: Alone,
                span: #0 bytes(0..0),
            },
            Literal { lit: Lit { kind: Integer, symbol: "1", suffix: None }, span: Span { lo: BytePos(0), hi: BytePos(0), ctxt: #0 } },
            Punct {
                ch: ',',
                spacing: Alone,
                span: #0 bytes(0..0),
            },
        ],
        span: #0 bytes(0..0),
    },
    Punct {
        ch: ';',
        spacing: Alone,
        span: #0 bytes(0..0),
    },
]

cc dtolnay/async-trait#63

@dtolnay dtolnay added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Jan 31, 2020
@Centril Centril self-assigned this Feb 1, 2020
@Centril
Copy link
Contributor

Centril commented Feb 1, 2020

I have a fix in #68737. The bug was in pretty printing (usually the case in these types of bugs).

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 1, 2020
pretty: print attrs in struct expr

Fixes rust-lang#68710 by printing the attributes on struct expression fields.

r? @petrochenkov
cc @dtolnay
@bors bors closed this as completed in cef6894 Feb 2, 2020
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants