syn
syn copied to clipboard
Help Request | Determining type from syn::Type
Hello!
I'm a little confused by syn::Type. I'm writing a derive macro and I really just need to know if a given field on the input struct is a String or a bool, otherwise it's invalid (at least for now). For instance, I need to create a new object with String::new() for each String member and false for each bool member. I've got
let component_field_inits = fields.iter().map(|field| {
let field_ident = field.ident.clone();
let field_type = field.ty.clone();
// let field_init = ... do some stuff
quote! { #field_ident: #field_init}
});
where fields is an &Punctuated<Field, Comma>. I feel like it's either a path or a Verbatim but I just don't know. I'd like to destructure my way there in two match arms (one for String and one for bool) and then use _ to panic otherwise. Any help would be appreciated.
Update: Current Solution ->
let ty_is_string = |field: &syn::Field| {
if let syn::Type::Path(ref p) = field.ty {
return p.path.segments.len() == 1 && p.path.segments[0].ident == "String";
}
false
};
let ty_is_bool = |field: &syn::Field| {
if let syn::Type::Path(ref p) = field.ty {
return p.path.segments.len() == 1 && p.path.segments[0].ident == "bool";
}
false
};
// Create the fields for initializing the struct
let component_field_inits = fields.iter().map(|field| {
let field_ident = field.ident.clone().unwrap();
if ty_is_string(field) {
quote! { #field_ident: String::new() }
} else if ty_is_bool(field) {
quote! { #field_ident: false }
} else {
panic!("Field type not supported");
}
});
This is basically copy pasted from (halfway through) Jon Gjengset's procedural macro video series. I'm sure I can improve this.
I was working on something similar and came across this issue - it's definitely not easy 😆 - so I have a solution that's similar to yours and works well, however - it falls apart when I have types with generics such as Option<T> - because, Ident will be Option, awesome, but then the args will be < String > so it seems like I'd have to write a parser to figure out the T - (using nom, or contains) - which seems like a rabbit hole. There must be an easier way 🤔
I ended up writing some sort of type checking helper functions that deal with options here: https://github.com/bcpeinhardt/formulaY/blob/main/src/util.rs The part about checking options is largely converted from a stack overflow answer.
Sorry that no one was able to provide guidance here. If this is still an issue, you could try taking this question to any of the resources shown in https://www.rust-lang.org/community. This library is one of the most widely used Rust libraries and plenty of people will be able to provide guidance about it.