diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 33a976d7b..b455b3d0f 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -445,14 +445,19 @@ fn deserialize_tuple( cattrs: &attr::Container, deserializer: Option, ) -> Fragment { + assert!(!cattrs.has_flatten()); + + let field_count = fields + .iter() + .filter(|field| !field.attrs.skip_deserializing()) + .count(); + let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - assert!(!cattrs.has_flatten()); - // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. @@ -493,19 +498,18 @@ fn deserialize_tuple( } }; let dispatch = if let Some(deserializer) = deserializer { - quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) + quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)) } else if is_enum { - quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) + quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)) } else if nfields == 1 { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { let type_name = cattrs.name().deserialize_name(); - quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) + quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { + let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) @@ -548,13 +552,18 @@ fn deserialize_tuple_in_place( cattrs: &attr::Container, deserializer: Option, ) -> Fragment { + assert!(!cattrs.has_flatten()); + + let field_count = fields + .iter() + .filter(|field| !field.attrs.skip_deserializing()) + .count(); + let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let delife = params.borrowed.de_lifetime(); - assert!(!cattrs.has_flatten()); - let is_enum = variant_ident.is_some(); let expecting = match variant_ident { Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident), @@ -580,19 +589,18 @@ fn deserialize_tuple_in_place( }; let dispatch = if let Some(deserializer) = deserializer { - quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr)) + quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)) } else if is_enum { - quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)) + quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr)) } else if nfields == 1 { let type_name = cattrs.name().deserialize_name(); quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { let type_name = cattrs.name().deserialize_name(); - quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #nfields, #visitor_expr)) + quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) }; - let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); - let visitor_var = if all_skipped { + let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 117cd3f4e..b5388c473 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1533,7 +1533,7 @@ fn test_invalid_length_enum() { Token::TupleVariant { name: "InvalidLengthEnum", variant: "B", - len: 3, + len: 2, }, Token::I32(1), Token::TupleVariantEnd,