Skip to content

Commit fd5b5e9

Browse files
committed
Correctly calculate has_flatten attribute in all cases for deserialization
Consequence: `FlattenSkipDeserializing[DenyUnknown]` - does not collect data in Field, because do not read them anyway - gets `deserialize_in_place` method - gets ability to deserialize from sequence (visit_seq method) - uses `deserialize_struct` instead of `deserialize_map`
1 parent 0647a7c commit fd5b5e9

File tree

3 files changed

+13
-39
lines changed

3 files changed

+13
-39
lines changed

serde_derive/src/de.rs

+13-17
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
285285
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
286286
}
287287
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
288-
deserialize_tuple(
289-
params,
290-
fields,
291-
&cont.attrs,
292-
cont.attrs.has_flatten(),
293-
TupleForm::Tuple,
294-
)
288+
deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
295289
}
296290
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
297291
}
@@ -465,11 +459,10 @@ fn deserialize_tuple(
465459
params: &Parameters,
466460
fields: &[Field],
467461
cattrs: &attr::Container,
468-
has_flatten: bool,
469462
form: TupleForm,
470463
) -> Fragment {
471464
assert!(
472-
!has_flatten,
465+
!has_flatten(fields),
473466
"tuples and tuple variants cannot have flatten fields"
474467
);
475468

@@ -590,7 +583,7 @@ fn deserialize_tuple_in_place(
590583
cattrs: &attr::Container,
591584
) -> Fragment {
592585
assert!(
593-
!cattrs.has_flatten(),
586+
!has_flatten(fields),
594587
"tuples and tuple variants cannot have flatten fields"
595588
);
596589

@@ -972,9 +965,7 @@ fn deserialize_struct(
972965
})
973966
.collect();
974967

975-
let has_flatten = fields
976-
.iter()
977-
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing());
968+
let has_flatten = has_flatten(fields);
978969
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten);
979970

980971
// untagged struct variants do not get a visit_seq method. The same applies to
@@ -1114,7 +1105,7 @@ fn deserialize_struct_in_place(
11141105
) -> Option<Fragment> {
11151106
// for now we do not support in_place deserialization for structs that
11161107
// are represented as map.
1117-
if cattrs.has_flatten() {
1108+
if has_flatten(fields) {
11181109
return None;
11191110
}
11201111

@@ -1830,7 +1821,6 @@ fn deserialize_externally_tagged_variant(
18301821
params,
18311822
&variant.fields,
18321823
cattrs,
1833-
variant.attrs.has_flatten(),
18341824
TupleForm::ExternallyTagged(variant_ident),
18351825
),
18361826
Style::Struct => deserialize_struct(
@@ -1930,7 +1920,6 @@ fn deserialize_untagged_variant(
19301920
params,
19311921
&variant.fields,
19321922
cattrs,
1933-
variant.attrs.has_flatten(),
19341923
TupleForm::Untagged(variant_ident, deserializer),
19351924
),
19361925
Style::Struct => deserialize_struct(
@@ -2703,7 +2692,7 @@ fn deserialize_map_in_place(
27032692
cattrs: &attr::Container,
27042693
) -> Fragment {
27052694
assert!(
2706-
!cattrs.has_flatten(),
2695+
!has_flatten(fields),
27072696
"inplace deserialization of maps does not support flatten fields"
27082697
);
27092698

@@ -3038,6 +3027,13 @@ fn effective_style(variant: &Variant) -> Style {
30383027
}
30393028
}
30403029

3030+
/// True if there are fields that is not skipped and has a `#[serde(flatten)]` attribute.
3031+
fn has_flatten(fields: &[Field]) -> bool {
3032+
fields
3033+
.iter()
3034+
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing())
3035+
}
3036+
30413037
struct DeImplGenerics<'a>(&'a Parameters);
30423038
#[cfg(feature = "deserialize_in_place")]
30433039
struct InPlaceImplGenerics<'a>(&'a Parameters);

serde_derive/src/internals/ast.rs

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ impl<'a> Container<'a> {
8585
for field in &mut variant.fields {
8686
if field.attrs.flatten() {
8787
has_flatten = true;
88-
variant.attrs.mark_has_flatten();
8988
}
9089
field.attrs.rename_by_rules(
9190
variant

serde_derive/src/internals/attr.rs

-21
Original file line numberDiff line numberDiff line change
@@ -810,18 +810,6 @@ pub struct Variant {
810810
rename_all_rules: RenameAllRules,
811811
ser_bound: Option<Vec<syn::WherePredicate>>,
812812
de_bound: Option<Vec<syn::WherePredicate>>,
813-
/// True if variant is a struct variant which contains a field with
814-
/// `#[serde(flatten)]`.
815-
///
816-
/// ```ignore
817-
/// enum Enum {
818-
/// Variant {
819-
/// #[serde(flatten)]
820-
/// some_field: (),
821-
/// },
822-
/// }
823-
/// ```
824-
has_flatten: bool,
825813
skip_deserializing: bool,
826814
skip_serializing: bool,
827815
other: bool,
@@ -991,7 +979,6 @@ impl Variant {
991979
},
992980
ser_bound: ser_bound.get(),
993981
de_bound: de_bound.get(),
994-
has_flatten: false,
995982
skip_deserializing: skip_deserializing.get(),
996983
skip_serializing: skip_serializing.get(),
997984
other: other.get(),
@@ -1034,14 +1021,6 @@ impl Variant {
10341021
self.de_bound.as_ref().map(|vec| &vec[..])
10351022
}
10361023

1037-
pub fn has_flatten(&self) -> bool {
1038-
self.has_flatten
1039-
}
1040-
1041-
pub fn mark_has_flatten(&mut self) {
1042-
self.has_flatten = true;
1043-
}
1044-
10451024
pub fn skip_deserializing(&self) -> bool {
10461025
self.skip_deserializing
10471026
}

0 commit comments

Comments
 (0)