Cannot generate struct instance when return it from proc macro method generated by quote!

In my proc macro I want to impl new method on struct. This method should return struct instance. For now I got an error like next:

error: expected identifier, found `"size"`
 --> src\main.rs:3:10
  |
3 | #[derive(Packet)]
  |          ^^^^^^
  |          |
  |          expected identifier
  |          while parsing this struct
  |
  = note: this error originates in the derive macro `Packet` (in Nightly builds, run with -Z macro-backtrace for more info)

error: proc-macro derive produced unparseable tokens
 --> src\main.rs:3:10
  |
3 | #[derive(Packet)]
  |          ^^^^^^

error[E0063]: missing fields `field2`, `field3`, `size` and 2 other fields in initializer of `Test`
 --> src\main.rs:3:10
  |
3 | #[derive(Packet)]
  |          ^^^^^^ missing `field2`, `field3`, `size` and 2 other fields

This is code of my proc macro:

#[proc_macro_derive(Packet, attributes(dynamic_field))]
pub fn derive(input: TokenStream) -> TokenStream {
    let ItemStruct { ident, fields, .. } = parse_macro_input!(input);

    let field_data = fields.iter().filter_map(|f| {
        let ident = f.ident.clone().unwrap().to_string();
        let field_type = f.ty.clone();
        let ident = format_ident!("{}", f.ident.as_ref().unwrap());

        if f.attrs.iter().any(|attr| attr.path.is_ident("dynamic_field")) {
            Some(quote! { Self::#ident(); })
        } else {
            None
        }
    }).collect::<Vec<_>>();

    let fields_names = fields.iter().map(|f| {
        let ident = f.ident.clone().unwrap().to_string();
        quote!(#ident)
    }).collect::<Vec<_>>();

    let value = quote!(1);

    let output = quote! {
        impl #ident {
            pub fn debug() {
                #(#field_data)*
            }

            pub fn from_binary(buffer: &Vec<u8>) -> Self {
                Self {
                    #(#fields_names: #value),*
                }
            }
        }
    };

    TokenStream::from(output)
}

Could somebody explain what am I doing wrong and how to fix this issue ?

Looks to me like you're putting a string literal where you want an identifier

let ident = f.ident.clone().unwrap().to_string();
quote!(#ident)

You want ident to be an ident but here it's a string, so quote is creating a string literal tokens rather than an ident

1 Like

thank you ! I replaced string with ident and now all compiled:

let fields_names = fields.iter().map(|f| {
	f.ident.clone()
}).collect::<Vec<_>>();
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.