diff --git a/serde_derive/src/internals/check.rs b/serde_derive/src/internals/check.rs index b01a8ca4d..16b16ae6b 100644 --- a/serde_derive/src/internals/check.rs +++ b/serde_derive/src/internals/check.rs @@ -318,6 +318,9 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { for variant in variants { match variant.style { Style::Struct => { + if variant.attrs.untagged() { + return + } for field in &variant.fields { let check_ser = !(field.attrs.skip_serializing() || variant.attrs.skip_serializing()); diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index 2b7d189fd..02c36c413 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -814,6 +814,100 @@ fn test_internally_tagged_enum() { ); } +#[test] +fn test_internally_tagged_enum_with_untagged_variant() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(tag = "kind")] + enum InternallyTagged { + Tagged { + a: u8, + }, + #[serde(untagged)] + Untagged { + kind: String, + b: u8, + }, + } + + assert_de_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Tagged { a: 1 }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("a"), + Token::U8(1), + Token::StructEnd, + ], + ); + + assert_de_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Map { len: Some(2) }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::MapEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Foo".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Foo"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); + + assert_tokens( + &InternallyTagged::Untagged { + kind: "Tagged".to_owned(), + b: 2, + }, + &[ + Token::Struct { + name: "InternallyTagged", + len: 2, + }, + Token::Str("kind"), + Token::Str("Tagged"), + Token::Str("b"), + Token::U8(2), + Token::StructEnd, + ], + ); +} + #[test] fn test_internally_tagged_bytes() { #[derive(Debug, PartialEq, Deserialize)]