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

Field attributes lost in proc macro input #68710

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