Non-items dropped in custom derive

595a288
Opened by antoyo at 2020-04-20 22:12:30

Hi. It looks like when you generate non-items in a custom derive, they are silently dropped. For instance, with the following custom derive:

#[proc_macro_derive(HelloWorld)]
pub fn hello_world(input: TokenStream) -> TokenStream {
    let ast = syn::parse(input).unwrap();
    let gen = impl_hello_world(&ast);
    gen.into()
}

fn impl_hello_world(ast: &syn::DeriveInput) -> quote::Tokens {
    let name = &ast.ident;
    quote! {{
        fn hello_world() {
            println!("Hello, World! My name is {}", stringify!(#name));
        }
        hello_world();
    }}
}

and the following code:

fn main() {
    #[derive(HelloWorld)]
    struct _Toto {
    }
}

nothing is printed on the screen. So, is it normal that non-items are dropped? Could they be generated as well if it makes sense (like in a struct that is defined within a function)? If not, if would be nice to have a least a warning when this happen. Thanks.

cc @jseyfried @alexcrichton @nikomatsakis

  1. It does seem like a warning (or error!) would be appropriate. I don't believe that custom derive was intended to be able to generate non-item content, however.

    Niko Matsakis at 2018-02-06 16:51:33

  2. Yeah, this should definitely be an error (or warning cycle, hopefully not...).

    Since the macro invocation is an item, the macro expansion is parsed as items. It looks like we are silently ignoring an error from the parser, which is scary.

    Jeffrey Seyfried at 2018-02-13 22:43:18

  3. Fortunately this issue doesn't affect proc_macro and proc_macro_attribute (https://github.com/rust-lang/rust/issues/38356).

    Vadim Petrochenkov at 2018-05-17 22:07:48