From fa06c1dafbce98d4eaa64b4af77d29d97743c040 Mon Sep 17 00:00:00 2001 From: Daniel Eades Date: Sun, 12 Jul 2026 12:33:54 +0100 Subject: [PATCH] Avoid clippy::unit_arg in generated builder code for unit-typed properties For struct properties whose type is the unit type () (produced by null schemas), the generated builder code passed a unit value to Ok(..) in the builder's Default impl and in the From impl, tripping clippy's warn-by-default unit_arg lint. Emit Ok(()) directly for such properties instead; this is semantically identical. --- typify-impl/src/type_entry.rs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/typify-impl/src/type_entry.rs b/typify-impl/src/type_entry.rs index 5f3b4897..8549ac72 100644 --- a/typify-impl/src/type_entry.rs +++ b/typify-impl/src/type_entry.rs @@ -1133,6 +1133,7 @@ impl TypeEntry { let mut prop_error = Vec::new(); let mut prop_type = Vec::new(); let mut prop_type_scoped = Vec::new(); + let mut prop_is_unit = Vec::new(); properties.iter().for_each(|prop| { prop_doc.push(prop.description.as_ref().map(|d| quote! { #[doc = #d] })); @@ -1143,6 +1144,7 @@ impl TypeEntry { )); let prop_type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap(); + prop_is_unit.push(matches!(prop_type_entry.details, TypeEntryDetails::Unit)); prop_type.push(prop_type_entry.type_ident(type_space, &None)); prop_type_scoped .push(prop_type_entry.type_ident(type_space, &Some("super".to_string()))); @@ -1264,10 +1266,31 @@ impl TypeEntry { quote! { value } }; - let prop_default = prop_default.iter().map(|pd| match pd { - PropDefault::None(err_msg) => quote! { Err(#err_msg.to_string()) }, - PropDefault::Default(default_fn) => quote! { Ok(#default_fn) }, - PropDefault::Custom(custom_fn) => quote! { Ok(super::#custom_fn) }, + // For unit-typed properties (produced by null schemas) the value is + // always `()`, so we emit `Ok(())` rather than passing the unit value + // to `Ok(..)`, which would trip clippy's `unit_arg` lint. + let prop_default = + prop_default + .iter() + .zip(&prop_is_unit) + .map(|(pd, is_unit)| match pd { + PropDefault::None(err_msg) => quote! { Err(#err_msg.to_string()) }, + PropDefault::Default(_) | PropDefault::Custom(_) if *is_unit => { + quote! { Ok(()) } + } + PropDefault::Default(default_fn) => quote! { Ok(#default_fn) }, + PropDefault::Custom(custom_fn) => quote! { Ok(super::#custom_fn) }, + }); + + // Per-property initializers for the `From` impl. Reading a + // unit field yields `()`, so we emit `Ok(())` directly to avoid + // passing a unit value to `Ok(..)` (clippy's `unit_arg` lint). + let prop_from = prop_name.iter().zip(&prop_is_unit).map(|(name, is_unit)| { + if *is_unit { + quote! { #name: Ok(()) } + } else { + quote! { #name: Ok(value.#name) } + } }); output.add_item( @@ -1327,7 +1350,7 @@ impl TypeEntry { fn from(#value_ident: super::#type_name) -> Self { Self { #( - #prop_name: Ok(value.#prop_name), + #prop_from, )* } }