From 89b4256e0820d74280ff46e8002a43b0ca3c664d Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:07:48 +0100 Subject: [PATCH 1/2] serde_derive: add fn sum_tokens --- serde_derive/src/ser.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 6eb3b0feb..88557ee9c 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -272,8 +272,9 @@ fn serialize_tuple_struct( let let_mut = mut_if(serialized_fields.peek().is_some()); - let len = serialized_fields - .map(|(i, field)| match field.attrs.skip_serializing_if() { + let len = sum_tokens( + quote!(0), + serialized_fields.map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let index = syn::Index { @@ -283,8 +284,8 @@ fn serialize_tuple_struct( let field_expr = get_member(params, field, &Member::Unnamed(index)); quote!(if #path(#field_expr) { 0 } else { 1 }) } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); + }), + ); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; @@ -293,6 +294,15 @@ fn serialize_tuple_struct( } } +fn sum_tokens(init: TokenStream, iter: impl Iterator) -> TokenStream { + let mut tokens = init; + for item in iter { + tokens.extend(quote!( + )); + tokens.extend(item); + } + tokens +} + fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { assert!( fields.len() as u64 <= u64::from(u32::MAX), From 1cc8999e4d1bac7fb72e9df9eb794492d68a4cce Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:43:11 +0100 Subject: [PATCH 2/2] serde_derive: use sum_tokens in all `let len =` calculations --- serde_derive/src/ser.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 88557ee9c..f9dbba272 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -294,6 +294,7 @@ fn serialize_tuple_struct( } } +/// `quote!(#init + #item + ...)` fn sum_tokens(init: TokenStream, iter: impl Iterator) -> TokenStream { let mut tokens = init; for item in iter { @@ -355,18 +356,16 @@ fn serialize_struct_as_struct( let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); - let len = serialized_fields - .map(|field| match field.attrs.skip_serializing_if() { + let len = sum_tokens( + quote!(#tag_field_exists as usize), + serialized_fields.map(|field| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = get_member(params, field, &field.member); quote!(if #path(#field_expr) { 0 } else { 1 }) } - }) - .fold( - quote!(#tag_field_exists as usize), - |sum, expr| quote!(#sum + #expr), - ); + }), + ); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; @@ -840,15 +839,16 @@ fn serialize_tuple_variant( let let_mut = mut_if(serialized_fields.peek().is_some()); - let len = serialized_fields - .map(|(i, field)| match field.attrs.skip_serializing_if() { + let len = sum_tokens( + quote!(0), + serialized_fields.map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = field_i(i); quote!(if #path(#field_expr) { 0 } else { 1 }) } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); + }), + ); match context { TupleVariant::ExternallyTagged { @@ -917,16 +917,17 @@ fn serialize_struct_variant( let let_mut = mut_if(serialized_fields.peek().is_some()); - let len = serialized_fields - .map(|field| { + let len = sum_tokens( + quote!(0), + serialized_fields.map(|field| { let member = &field.member; match field.attrs.skip_serializing_if() { Some(path) => quote!(if #path(#member) { 0 } else { 1 }), None => quote!(1), } - }) - .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); + }), + ); match context { StructVariant::ExternallyTagged {