diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 74df11df..3f4704c2 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1377,42 +1377,37 @@ fn deserialize_adjacently_tagged_enum( } }; - fn is_unit(variant: &Variant) -> bool { - match variant.style { - Style::Unit => true, - Style::Struct | Style::Tuple | Style::Newtype => false, - } - } + let arms = variants + .iter() + .enumerate() + .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) + .filter_map(|(i, variant)| { + let variant_index = field_i(i); + let variant_ident = &variant.ident; - let mut missing_content = quote! { - _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) - }; - if variants.iter().any(is_unit) { - let fallthrough = if variants.iter().all(is_unit) { - None - } else { - Some(quote! { - _ => #missing_content - }) - }; - let arms = variants - .iter() - .enumerate() - .filter(|&(_, variant)| !variant.attrs.skip_deserializing() && is_unit(variant)) - .map(|(i, variant)| { - let variant_index = field_i(i); - let variant_ident = &variant.ident; - quote! { - __Field::#variant_index => _serde::export::Ok(#this::#variant_ident), + let arm = match variant.style { + Style::Unit => quote! { + _serde::export::Ok(#this::#variant_ident) + }, + Style::Newtype if variant.attrs.deserialize_with().is_none() => { + let span = variant.original.span(); + let func = quote_spanned!(span=> _serde::private::de::missing_field); + quote! { + #func(#content).map(#this::#variant_ident) + } } - }); - missing_content = quote! { - match __field { - #(#arms)* - #fallthrough - } - }; - } + _ => return None, + }; + Some(quote! { + __Field::#variant_index => #arm, + }) + }); + let missing_content = quote! { + match __field { + #(#arms)* + _ => _serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) + } + }; // Advance the map by one key, returning early in case of error. let next_key = quote! { diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index d4456bed..c0c807ec 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -1145,6 +1145,20 @@ fn test_adjacently_tagged_enum() { ], ); + // optional newtype with no content field + assert_de_tokens( + &AdjacentlyTagged::Newtype::>(None), + &[ + Token::Struct { + name: "AdjacentlyTagged", + len: 1, + }, + Token::Str("t"), + Token::Str("Newtype"), + Token::StructEnd, + ], + ); + // tuple with tag first assert_tokens( &AdjacentlyTagged::Tuple::(1, 1),