0

I want to add some syn::Ident's to form a &'static str. All Idents should be concat to form a comma separated and stringified (because that's how I get a string representation of an Ident) &'static str.

I got a non-working project here: https://github.com/Jasperav/comma_separated (inside the example folder there is a failing test).

This is my test:

#[test]
fn test_another_struct() {
    assert_eq!("name, another_name", AnotherStruct::useless())
}

It fails because of this:

Expected :nameanother_name Actual :name, another_name

This is my code trying to generated the comma separated list (inside lib.rs):

let idents = vec![
    syn::Ident::new("name", Span::call_site()),
    syn::Ident::new("another_name", Span::call_site())
];

proc_macro::TokenStream::from(quote! {
    impl #struct_name {
        fn useless() -> &'static str {
            concat!(#(stringify!(#idents)),*)
        }
    }
})

I don't understand why it's not working. There is 1 , in my macro, that means: separate everything with a comma right?

J. Doe
  • 12,159
  • 9
  • 60
  • 114

1 Answers1

1

If you cargo expand your code, you would realize you expanded into this:

(suppose struct_name is Foo)

impl Foo {
    fn useless() -> &'static str {
        concat!(stringify!(name), stringify!(another_name))
    }
}

stringify! converts the ident into string directly, so the returned value is equivalent to

concat!("name", "another_name")

Here, comma is a separator for the syntax, not a string literal, so you end up getting nameanother_name.

Only considering your code above, the most convenient fix is to formulate the raw string inside proc_macro code instead of relying on stringify! and concat!, allowing you to use APIs like slice::join.

SOFe
  • 7,867
  • 4
  • 33
  • 61