diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 4c39b7ca..c6b2cfff 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1749,10 +1749,14 @@ fn deserialize_untagged_enum_after( ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); - // This may be infallible so we need to provide the error type. + // Ignore any error associated with non-untagged deserialization so that we + // can fall through to the untagged variants. This may be infallible so we + // need to provide the error type. let first_attempt = first_attempt.map(|expr| { quote! { - if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = #expr { + if let _serde::__private::Result::<_, __D::Error>::Ok(__ok) = (|| { + #expr + })() { return _serde::__private::Ok(__ok); } } diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index eeb3ec0d..9c4eabbb 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -2381,11 +2381,12 @@ fn test_partially_untagged_enum_desugared() { } #[test] -fn test_partially_untagged_simple_enum() { +fn test_partially_untagged_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t")] enum Data { A, + B, #[serde(untagged)] Var(u32), } @@ -2398,11 +2399,44 @@ fn test_partially_untagged_simple_enum() { Token::Map { len: None }, Token::Str("t"), Token::Str("A"), - Token::Str("b"), - Token::I32(0), Token::MapEnd, ], ); + + let data = Data::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(tag = "t", content = "c")] + enum Data2 { + A(u32), + B, + #[serde(untagged)] + Var(u32), + } + + let data = Data2::A(7); + + assert_de_tokens( + &data, + &[ + Token::Map { len: None }, + Token::Str("t"), + Token::Str("A"), + Token::Str("c"), + Token::U32(7), + Token::MapEnd, + ], + ); + + let data = Data2::Var(42); + + assert_de_tokens(&data, &[Token::U32(42)]); + + // TODO test error output } #[test]