Search code examples
rustrust-macros

How do you get the type of an impl block in a Rust procedural macro?


I'm trying to write a Rust procedural macro that can be applied to an impl block like this;

struct SomeStruct { }

#[my_macro]
impl SomeStruct { }

I'm using syn and quote to parse and format TokenStreams in the macro. It looks something like this:

#[proc_macro_attribute]
pub fn my_macro(meta: TokenStream, code: TokenStream) -> TokenStream {
    let input = parse_macro_input!(code as ItemImpl);

    // ...

    TokenStream::from(quote!(#input))
}

Is there a way to access the type name of the impl block using syn? I don't see any field in ItemImpl that gives me that information.


Solution

  • The documentation lists 9 fields on an ItemImpl:

    1. attrs: Vec<Attribute>
    2. defaultness: Option<Default>
    3. unsafety: Option<Unsafe>
    4. impl_token: Impl
    5. generics: Generics
    6. trait_: Option<(Option<Bang>, Path, For)>
    7. self_ty: Box<Type>
    8. brace_token: Brace
    9. items: Vec<ImplItem>

    Only one of those has the word "type" in it: self_ty.

    use syn; // 0.15.23
    
    fn example(input: syn::ItemImpl) {
        println!("{:#?}", input.self_ty);
    }
    
    fn main() {
        let code = syn::parse_str(
            r###"
            impl Foo {}
            "###,
        )
        .unwrap();
    
        example(code);
    }
    
    Path(
        TypePath {
            qself: None,
            path: Path {
                leading_colon: None,
                segments: [
                    PathSegment {
                        ident: Ident(
                            Foo
                        ),
                        arguments: None
                    }
                ]
            }
        }
    )