-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Procedural macro attributes can't be applied to struct fields #53012
Comments
I would not want proc macro attributes to be allowed on struct fields, just as a decl macro cannot expand to one field of a struct. Proc macro attributes should remain conceptually as a way to pass a fragment of syntax as the input to an eagerly expanded proc macro and the following is not allowed. pub struct Foo {
// do not allow
nop! {
pub foo_field: u32,
}
} Instead I would want #[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream;
#[proc_macro_attribute(attributes(serde))]
pub fn derive_serialize_as_an_attribute(args: TokenStream, input: TokenStream) -> TokenStream; #[derive(Serialize)]
pub struct Foo {
#[serde(...)]
pub foo_field: u32,
}
#[derive_serialize_as_an_attribute]
pub struct Foo {
#[serde(...)]
pub foo_field: u32,
} |
That would work for me, but would there be inconsistency between how |
@mjbshaw it is intentional. Inserting invisible items into an impl block is not at all disruptive while inserting invisible fields into a struct affects its use in struct literals. We may allow it at some point, possibly with restrictions like we have for macros in expression position (they must expand to exactly one expression), but we should not allow proc macro attributes on struct fields before we allow bang macros around struct fields. pub struct Foo {
// If this expands to more than one field, I can no longer write
// the struct literal `Foo { foo_field: 0 }`.
not_noop! {
pub foo_field: u32,
}
}
impl Foo {
// If this expands to more than one impl item there is no disruption.
not_noop! {
fn method(&self) {}
}
} |
Thanks for the explanation, @dtolnay. Respectfully, I have to disagree with the justification for disallowing this. My counterarguments are: not_noop! {
pub struct Foo {
pub foo_field: u32,
}
} macro_rules! not_noop {
( pub fn $ident:ident ( $($args:tt)* ) {} ) => {
pub fn $ident(_: usize, $($args)*) {}
}
}
pub struct Foo;
impl Foo {
not_noop! {
pub fn method() {}
}
}
pub fn call_foo_method() {
// I can no longer call Foo::method(). I need to pass in a usize.
Foo::method(0usize);
} I don't believe the disallowance of a (attribute) macro within a struct item provides any benefit. It just unnecessarily hinders users. |
Triage: don't think anything has changed here, not sure if it's going to. |
Current error: struct S {
#[global_allocator]
field: u8
}
fn main() {}
This is a language extension, so it should go through RFC or similar process. |
I would really appreciate this feature. |
Given the simple program:
And the corresponding definition of the
#[nop]
attribute:Attempting to compile this results in the error:
The problem is the
#[nop]
attribute onfoo_field
. If it's removed, the library compiles fine. I believe this is incorrect and that the code should compile as-is. The#[nop]
macro can be applied tofoo_fn
just fine; it seems wrong that it doesn't work withfoo_field
.Rust version:
rustc --version
:rustc 1.29.0-nightly (97085f9fb 2018-08-01)
Please let me know if there's anything I can do to be of assistance.
Here's a bash script that fully reproduces the issue:
The text was updated successfully, but these errors were encountered: