Skip to content

Commit

Permalink
Point out serde(untagged) variants which are out of order
Browse files Browse the repository at this point in the history
Previously if someone wrote an enum containing:

- `A` (untagged)
- `B` (tagged)
- `C` (tagged)
- `D` (untagged)
- `E` (tagged)
- `F` (untagged)

serde_derive would produce errors referring to B and E only, saying
you're supposed to put untagged variants at the end. The choice of B and
E for this error doesn't make a lot of sense because in order to resolve
the issue, the user must either:

- move A and D down

or:

- move B, C, and E up.

This commit changes the error to appear on A and D instead.
  • Loading branch information
dtolnay committed Jun 8, 2023
1 parent b63c65d commit a398237
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 8 deletions.
20 changes: 14 additions & 6 deletions serde_derive/src/internals/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ fn enum_from_ast<'a>(
variants: &'a Punctuated<syn::Variant, Token![,]>,
container_default: &attr::Default,
) -> Vec<Variant<'a>> {
let mut seen_untagged = false;
variants
let variants: Vec<Variant> = variants
.iter()
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
Expand All @@ -154,12 +153,21 @@ fn enum_from_ast<'a>(
fields,
original: variant,
}
}).inspect(|variant| {
if !variant.attrs.untagged() && seen_untagged {
})
.collect();

let index_of_last_tagged_variant = variants
.iter()
.rposition(|variant| !variant.attrs.untagged());
if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant {
for variant in &variants[..index_of_last_tagged_variant] {
if variant.attrs.untagged() {
cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum");
}
seen_untagged = variant.attrs.untagged();
}).collect()
}
}

variants
}

fn struct_from_ast<'a>(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: all variants with the #[serde(untagged)] attribute must be placed at the end of the enum
--> tests/ui/enum-representation/partially_tagged_wrong_order.rs:7:5
--> tests/ui/enum-representation/partially_tagged_wrong_order.rs:6:5
|
7 | B(String),
6 | A(u8),
| ^

0 comments on commit a398237

Please sign in to comment.