diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 64113a603..c3b779bf9 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1379,42 +1379,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 { + 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) + } + } + _ => return None, + }; Some(quote! { - _ => #missing_content + __Field::#variant_index => #arm, }) - }; - 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), - } - }); - missing_content = quote! { - match __field { - #(#arms)* - #fallthrough - } - }; - } + }); + 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 d4456bed7..c0c807ec7 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),