From 388c5db075317f9a2f62c3ffe64e5dda4ab58131 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Mon, 4 Aug 2025 14:39:34 -0400 Subject: [PATCH] serde_derive: fix ser/de inconsistency with skipped enum variants When serde_derive generates Serialize/Deserialize implementations for an enum with #[serde(skipped)] variants, it leaves a gap in the assigned `variant_index`es for the variants (i.e., includes skipped variants in the count) in the Serialize impl, but excludes skipped variants in the count in the Deserialize impl. This means that non-self-describing data formats that rely on variant indices instead of variant names cannot correctly serialize+deserialize enums with skipped variants. This changes the generated Serialize impl to match the deserialize impl by excluding skipped variants from the count. This is also consistent with how #[serde(skip)] affects field indices in structs. Fixes #2614 --- serde_derive/src/ser.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 46be736c4..5895dc625 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -396,9 +396,12 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont let mut arms: Vec<_> = variants .iter() - .enumerate() - .map(|(variant_index, variant)| { - serialize_variant(params, variant, variant_index as u32, cattrs) + .scan(0, |next_variant_index, variant| { + let variant_index = *next_variant_index; + if !variant.attrs.skip_serializing() { + *next_variant_index += 1; + } + Some(serialize_variant(params, variant, variant_index, cattrs)) }) .collect();