From 6fb82e13b90b7c5362e69cb542a13eb9b25b9e49 Mon Sep 17 00:00:00 2001 From: naskya Date: Tue, 16 Jul 2024 02:11:16 +0900 Subject: [PATCH] fix: incorrect merge logic --- crates/relax-macros/src/lib.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) 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)*