From 93b84c02b3e488f5db073100c4fd0f895ecdb002 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 22 May 2023 23:48:14 +0500 Subject: [PATCH] Correctly process skipped fields in visit_newtype_struct Changes in generated code (see the file attached to PR): Tuple1as0: Tuple1as0Default: Tuple1as0With: fixed visit_newtype_struct: use default value instead of deserializing it This fixes compilation error for Deserialize side of Tuple1as0(Skipped) tuple --- serde_derive/src/de.rs | 92 ++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 28b4bc38ad..002d36e55b 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -509,33 +509,30 @@ fn deserialize_tuple( let visit_newtype_struct = match form { TupleForm::Tuple if nfields == 1 => { - let field = &fields[0]; - let field_ty = field.ty; - - let value = match field.attrs.deserialize_with() { - None => { - let span = field.original.span(); - let func = - quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); - quote! { - #func(__e)? + let visit_newtype_struct = Stmts(read_fields_in_order( + &type_path, + params, + fields, + false, + cattrs, + expecting, + |_, _, field, _| match field.attrs.deserialize_with() { + None => { + let field_ty = field.ty; + let span = field.original.span(); + let func = + quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); + quote! { + #func(__e)? + } } - } - Some(path) => { - quote! { - #path(__e)? + Some(path) => { + quote! { + #path(__e)? + } } - } - }; - - let mut result = quote!(#type_path(__field0)); - if params.has_getter { - let this_type = ¶ms.this_type; - let (_, ty_generics, _) = params.generics.split_for_impl(); - result = quote! { - _serde::__private::Into::<#this_type #ty_generics>::into(#result) - }; - } + }, + )); Some(quote! { #[inline] @@ -543,8 +540,7 @@ fn deserialize_tuple( where __E: _serde::Deserializer<#delife>, { - let __field0: #field_ty = #value; - _serde::__private::Ok(#result) + #visit_newtype_struct } }) } @@ -653,9 +649,43 @@ fn deserialize_tuple_in_place( let nfields = fields.len(); let visit_newtype_struct = if !is_enum && nfields == 1 { - // We do not generate deserialize_in_place if every field has a - // deserialize_with. - assert!(fields[0].attrs.deserialize_with().is_none()); + // We deserialize newtype, so only one field is not skipped + let index = fields + .iter() + .position(|field| !field.attrs.skip_deserializing()) + .unwrap_or(0); + let index = Index::from(index); + let mut deserialize = quote! { + _serde::Deserialize::deserialize_in_place(__e, &mut self.place.#index) + }; + let write_defaults = fields.iter().enumerate().filter_map(|(index, field)| { + if field.attrs.skip_deserializing() { + let index = Index::from(index); + let default = Expr(expr_is_missing(field, cattrs)); + return Some(quote!(self.place.#index = #default;)); + } + None + }); + // If there are no deserialized fields, write only defaults + if field_count == 0 { + deserialize = quote! { + #(#write_defaults)* + _serde::__private::Ok(()) + } + } else + // Deserialize and write defaults if at least one field is skipped, + // otherwise only deserialize + if nfields > field_count { + deserialize = quote! { + match #deserialize { + _serde::__private::Ok(_) => { + #(#write_defaults)* + _serde::__private::Ok(()) + } + _serde::__private::Err(__err) => _serde::__private::Err(__err), + } + } + } Some(quote! { #[inline] @@ -663,7 +693,7 @@ fn deserialize_tuple_in_place( where __E: _serde::Deserializer<#delife>, { - _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) + #deserialize } }) } else {