diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index 8f580e31..a7d72e1c 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -358,16 +358,30 @@ impl Container { Meta(NameValue(ref m)) if m.ident == "tag" => { if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) { match item.data { - syn::Data::Enum(_) | - syn::Data::Struct(_, ..) => { + syn::Data::Enum(_) => { internal_tag.set(&m.ident, s.value()); } + syn::Data::Struct(syn::DataStruct{ref fields, ..}) => { + match *fields { + syn::Fields::Named(_) => { + internal_tag.set(&m.ident, s.value()); + }, + syn::Fields::Unnamed(_) | syn::Fields::Unit => { + cx.error_spanned_by( + fields, + "#[serde(tag = \"...\")] can only be used on enums \ + and structs with named fields", + ); + } + } + } syn::Data::Union(syn::DataUnion { ref union_token, .. }) => { cx.error_spanned_by( union_token, - "#[serde(tag = \"...\")] can only be used on enums", + "#[serde(tag = \"...\")] can only be used on enums \ + and structs with named fields", ); } } diff --git a/test_suite/tests/test_macros.rs b/test_suite/tests/test_macros.rs index c12a3f46..1eea8f10 100644 --- a/test_suite/tests/test_macros.rs +++ b/test_suite/tests/test_macros.rs @@ -1411,7 +1411,6 @@ fn test_internally_tagged_struct() { Token::StructEnd, ], ); - } #[test] diff --git a/test_suite/tests/ui/struct-representation/internally-taged-tuple.rs b/test_suite/tests/ui/struct-representation/internally-taged-tuple.rs new file mode 100644 index 00000000..78437f17 --- /dev/null +++ b/test_suite/tests/ui/struct-representation/internally-taged-tuple.rs @@ -0,0 +1,11 @@ +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] +#[serde(tag = "type")] +struct S ( + u8, + u8 +); + +fn main() {} diff --git a/test_suite/tests/ui/struct-representation/internally-taged-tuple.stderr b/test_suite/tests/ui/struct-representation/internally-taged-tuple.stderr new file mode 100644 index 00000000..6bae9760 --- /dev/null +++ b/test_suite/tests/ui/struct-representation/internally-taged-tuple.stderr @@ -0,0 +1,12 @@ +error: #[serde(tag = "...")] can only be used on enums and structs with named fields + --> $DIR/internally-taged-tuple.rs:6:10 + | +6 | struct S ( + | __________^ +7 | | u8, +8 | | u8 +9 | | ); + | |_^ + +error: aborting due to previous error + diff --git a/test_suite/tests/ui/struct-representation/internally-tagged-unit.rs b/test_suite/tests/ui/struct-representation/internally-tagged-unit.rs new file mode 100644 index 00000000..cd38cd76 --- /dev/null +++ b/test_suite/tests/ui/struct-representation/internally-tagged-unit.rs @@ -0,0 +1,8 @@ +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] +#[serde(tag = "type")] +struct U; + +fn main() {} diff --git a/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr b/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr new file mode 100644 index 00000000..ba0cbb40 --- /dev/null +++ b/test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr @@ -0,0 +1,8 @@ +error: #[serde(tag = "...")] can only be used on enums and structs with named fields + --> $DIR/internally-tagged-unit.rs:4:10 + | +4 | #[derive(Serialize)] + | ^^^^^^^^^ + +error: aborting due to previous error +