diff --git a/crates/relax-macros/src/lib.rs b/crates/relax-macros/src/lib.rs index e2d2710..f21baaf 100644 --- a/crates/relax-macros/src/lib.rs +++ b/crates/relax-macros/src/lib.rs @@ -137,7 +137,7 @@ fn derive_impl(input: syn::DeriveInput) -> syn::Result { if field.attrs.iter().any(|attr| attr.path().is_ident("relax")) { // nested - Ok(quote! { #vis #name: ::std::option::Option<<#ty as ::relax::Relax>::Partial> }) + Ok(quote! { #vis #name: ::std::option::Option<<#ty as Relax>::Partial> }) } else { // not nested match get_generic_ty("Option", ty) { @@ -176,10 +176,25 @@ fn derive_impl(input: syn::DeriveInput) -> syn::Result { }) }).collect::>>()?; - let merge_fields = fields.iter().map(|field| { + let merge_fields = fields.iter().map(|field| -> syn::Result { let name = field.ident.as_ref(); - quote! { #name: self.#name.or(optb.#name) } - }); + let nested = field + .attrs + .iter() + .any(|attr| attr.path().is_ident("relax")); + + Ok(match nested { + false => quote! { #name: self.#name.or(optb.#name) }, + true => quote! { + #name: match (self.#name, optb.#name) { + (::std::option::Option::Some(a), ::std::option::Option::None) => ::std::option::Option::Some(a), + (::std::option::Option::None, ::std::option::Option::Some(b)) => ::std::option::Option::Some(b), + (::std::option::Option::None, ::std::option::Option::None) => ::std::option::Option::None, + (::std::option::Option::Some(a), ::std::option::Option::Some(b)) => ::std::option::Option::Some(a.merge(b)), + } + } + }) + }).collect::>>()?; Ok(quote! { #(#extra_attrs)*