I have the following construct in a Derive procedural macro for generating a From implementation.
quote! {
impl From<#other_struct_name> for #this_struct_name {
fn from(other: #other_struct_name) -> Self {
Self {
#(#fields_from_other)*
}
}
}
}
other_struct_name is an attribute defined by the user to indicate which struct to use to clone from. Within fields_from_other I have this
let fields_from_other = fields.iter().map(|f| {
let ty = &f.ty;
let name = &f.ident;
quote! {
#name: other.#name,
}
});
fields are the fields of the struct I use the derive macro on so getting the type for those is not an issue. But how can I get the type of other.#name here? Eventually, I would like to check if it is an Option.
You cannot get type information (which includes the fields belonging to a
struct) at this point, because macro expansion happens on the AST, which is an untyped representation of the code. Consider also that if this were possible, what would happen if you applied your macro to twostructs which would reference each other?Maybe you can achieve what you want without having type information? Since you mention "checking if a field is an
Option", I'm guessing you want to apply different logic (likeunwrap_or_default()) onOption-typed fields.Some possible workarounds that come to mind:
structwith thederivemacro, you could annotate individual fields with a new attribute e.g.#[unwrap]or#[unwrap_or(some_value)], then parse these attributes in thederivemacro implementation.trait Copyable, then implementimpl Copyable for i32 { ... }as well asimpl Copyable for Option<i32> { ... }. In the generatedFromimplementation, you can then invoke these as e.g.#field: Copyable::copy(&other.#field).