Syn+quote compare types with lifetimes

In procedural macros I want match several types: &str, Option<&str>, &[u8] and so on.

But I can not write just:

macro_rules! parse_type {
    ($($tt:tt)*) => {{
        let ty: syn::Type = syn::parse_quote! { $($tt)* };
        ty
    }}
}

if ty == parse_type! { &str } // (1)

because of type can be &'a str, and (1) failed.

So any simple way to normalize types before compare,
like fn strip_liftimes(_: syn::Type) -> syn::Type,
that accept &'a str, &'b str and return &str?

In this case, syn::Type will be Type::Reference, which contains syn::TypeReference, which has the public field lifetime. Just set it to None, like this:

fn strip_lifetimes(ty: Type) -> Type {
    match ty {
        Reference(ty) => Reference(TypeReference { lifetime: None, ..ty }),
        ty => ty,
    }
}

Playground

2 Likes

Careful, type comparison like that is brittle: what if somebody did type Str = &'static str;, and provided Str to your macro?

Consider emitting code with the macro that uses poorman's specialization instead, or just assuming the given type is the one you expected, and let the type mismatches themselves nudge the caller of the macro to use the correct type :slightly_smiling_face:

1 Like