I'm trying to figure out what the inner type is in an Option type. I'm creating a derive macro called Builder
Say I have this struct:
#[derive(Debug, Default, Builder)]
pub struct Test {
foo: Option<String>,
}
Then I want to refer to the String part. I figured out how to check if it's an Option by reading this question: How can a procedural macro check a generic type for Option<Option<T>> and flatten it down to a single Option?
But I can only see that the type is an Option, not what its generics are. How do I find them? It must be stored somewhere
This is a small portion of what I have:
#[proc_macro_derive(Builder)]
pub fn derive_builder(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse_macro_input!(input as DeriveInput);
impl_builder(&ast).into()
}
fn impl_builder(ast: &syn::DeriveInput) -> TokenStream {
let fields = get_fields(&ast.data);
let setters = fields.named.iter().map(|field| {
let name = field.ident.as_ref().unwrap();
let ty = &field.ty;
if is_option(&ty) {
// ----------------------------------------------------------
// | I want to know what the inner type of Test.foo is here |
// | What to do here to get String? |
// ----------------------------------------------------------
} else {
// Default behaviour
let function_signature = quote!(pub fn #name (self, input: #ty) -> Self);
quote!(
#function_signature {
let mut data = self.data;
data.#name = input;
Self {
data
}
}
)
}
});
quote!{
#(#setters)*
}
}
fn get_fields(data: &Data) -> FieldsNamed {
if let Data::Struct(strct) = data {
if let Fields::Named(fields) = &strct.fields {
fields.to_owned()
} else {
panic!("Can only handle named fields")
}
} else {
panic!("Can only handle structs");
}
}
A little(?) juggling and you get it: