Skip to content

Commit

Permalink
Correctly process skipped fields in visit_newtype_struct
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Mingun committed Aug 2, 2023
1 parent 8cb578a commit 76e63ea
Showing 1 changed file with 61 additions and 31 deletions.
92 changes: 61 additions & 31 deletions serde_derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,42 +509,38 @@ 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 = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! {
_serde::__private::Into::<#this_type #ty_generics>::into(#result)
};
}
},
));

Some(quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
let __field0: #field_ty = #value;
_serde::__private::Ok(#result)
#visit_newtype_struct
}
})
}
Expand Down Expand Up @@ -647,17 +643,51 @@ fn deserialize_tuple_in_place(
let nfields = fields.len();

let visit_newtype_struct = if 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]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
#deserialize
}
})
} else {
Expand Down

0 comments on commit 76e63ea

Please sign in to comment.