Skip to content

Commit 9c0577a

Browse files
committed
Refactor: Extract field bound generation into helper function
1 parent 7d7249b commit 9c0577a

File tree

1 file changed

+35
-32
lines changed

1 file changed

+35
-32
lines changed

diesel_derives/src/insertable.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ fn derive_into_single_table(
4040
let mut ref_field_ty = Vec::with_capacity(model.fields().len());
4141
let mut ref_field_assign = Vec::with_capacity(model.fields().len());
4242

43-
// Collect explicit trait bounds with field spans to preserve error locations
44-
// when #[diagnostic::do_not_recommend] is used
43+
// Explicit trait bounds to improve error messages
4544
let mut field_ty_bounds = Vec::with_capacity(model.fields().len());
4645

4746
for field in model.fields() {
@@ -104,21 +103,12 @@ fn derive_into_single_table(
104103
treat_none_as_default_value,
105104
)?);
106105

107-
// Generate explicit trait bound with field span to preserve error location
108-
// This ensures errors point to the specific field when using #[diagnostic::do_not_recommend]
109-
let column_name = field.column_name()?.to_ident()?;
110-
let span = Span::mixed_site().located_at(field.span);
111-
let ty_to_check = if treat_none_as_default_value {
112-
inner_of_option_ty(&field.ty)
113-
} else {
114-
&field.ty
115-
};
116-
117-
field_ty_bounds.push(quote_spanned! {span=>
118-
#ty_to_check: diesel::expression::AsExpression<
119-
<#table_name::#column_name as diesel::Expression>::SqlType
120-
>
121-
});
106+
field_ty_bounds.push(generate_field_bound(
107+
field,
108+
table_name,
109+
&field.ty,
110+
treat_none_as_default_value,
111+
)?);
122112
}
123113
(Some(AttributeSpanWrapper { item: ty, .. }), false) => {
124114
direct_field_ty.push(field_ty_serialize_as(
@@ -134,21 +124,12 @@ fn derive_into_single_table(
134124
treat_none_as_default_value,
135125
)?);
136126

137-
// Generate explicit trait bound for serialize_as fields with field span
138-
// This ensures errors point to the specific field when using #[diagnostic::do_not_recommend]
139-
let column_name = field.column_name()?.to_ident()?;
140-
let span = Span::mixed_site().located_at(field.span);
141-
let ty_to_check = if treat_none_as_default_value {
142-
inner_of_option_ty(ty)
143-
} else {
144-
ty
145-
};
146-
147-
field_ty_bounds.push(quote_spanned! {span=>
148-
#ty_to_check: diesel::expression::AsExpression<
149-
<#table_name::#column_name as diesel::Expression>::SqlType
150-
>
151-
});
127+
field_ty_bounds.push(generate_field_bound(
128+
field,
129+
table_name,
130+
ty,
131+
treat_none_as_default_value,
132+
)?);
152133

153134
generate_borrowed_insert = false; // as soon as we hit one field with #[diesel(serialize_as)] there is no point in generating the impl of Insertable for borrowed structs
154135
}
@@ -332,3 +313,25 @@ fn field_expr(
332313
Ok(quote!(diesel::ExpressionMethods::eq(#column, #lifetime self.#field_name)))
333314
}
334315
}
316+
317+
/// Generate explicit trait bound with field span to improve error messages
318+
fn generate_field_bound(
319+
field: &Field,
320+
table_name: &Path,
321+
ty: &Type,
322+
treat_none_as_default_value: bool,
323+
) -> Result<TokenStream> {
324+
let column_name = field.column_name()?.to_ident()?;
325+
let span = Span::mixed_site().located_at(field.span);
326+
let ty_to_check = if treat_none_as_default_value {
327+
inner_of_option_ty(ty)
328+
} else {
329+
ty
330+
};
331+
332+
Ok(quote_spanned! {span=>
333+
#ty_to_check: diesel::expression::AsExpression<
334+
<#table_name::#column_name as diesel::Expression>::SqlType
335+
>
336+
})
337+
}

0 commit comments

Comments
 (0)