Search code examples
rustmacrosrust-proc-macros

How to find the correct return type for syn::parse?


I have a TokenStream that comes from the definition of a Rust function. I want to parse it with syn::parse (and .unrwap()). However, I don't know what the return type is supposed to be:

let ast: ??? = syn::parse(token_stream_from_function_definition).unwrap();

What should the type of ast be?


Solution

  • The syn::parse function tries to parse a TokenStream into whatever you expect it to be. As the documentation says:

    Parse tokens of source code into the chosen syntax tree node.

    It takes a type parameter, which you usually provide using type inference. For example, if you were expecting to parse a function declaration:

    let fn_decl: syn::FnDecl = syn::parse(token_stream).unwrap();
    

    This would panic if it was unable to parse a fn declaration.


    If you don't know exactly what to expect then you can be more general, matching a set of possibilities and then inspecting what you find. There are some enums provided for groups of syntax that can appear in the same places. For example, if you are parsing code in a context where you expect to find a function declaration or some other declarations on the same level, you probably need to parse an Item and then match on all of the possible types of item:

    use syn::Item;
    
    let item: Item = syn::parse(token_stream).unwrap();
    match item {
        Item::Fn(fn_decl) => {}
        Item::Mod(mod_item) => {}
        Item::Struct(struct_item) => {}
        Item::Enum(enum_item) => {}
        _ => {}
    }
    

    Note that syn::Item has 18 variants to match, and syn::Expr has 40! It's definitely worth narrowing down the possibilities and choosing the type to parse into that is the most specific for your needs. You might also consider defining your own type, representing the various syntactic constructs that you expect to find, and then implementing the syn::Parse trait manually.