Skip to main content

diesel_derives/
insertable.rs

1use std::collections::{HashMap, HashSet};
2
3use diesel_attribute_parser::AttributeSpanWrapper;
4use proc_macro2::{Span, TokenStream};
5use quote::quote;
6use quote::quote_spanned;
7use syn::spanned::Spanned as _;
8use syn::{DeriveInput, Expr, Path, Result, Type};
9use syn::{Lifetime, parse_quote};
10
11use crate::field::Field;
12use crate::model::Model;
13use crate::util::{inner_of_option_ty, is_option_ty, wrap_in_dummy_mod};
14
15pub fn derive(item: DeriveInput) -> Result<TokenStream> {
16    let model = Model::from_item(&item, false, true)?;
17
18    let tokens = model
19        .table_names()
20        .iter()
21        .map(|table_name| derive_into_single_table(&item, &model, table_name))
22        .collect::<Result<Vec<_>>>()?;
23
24    Ok(wrap_in_dummy_mod({
    let mut _s = ::quote::__private::TokenStream::new();
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut tokens, i) = tokens.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let tokens =
                match tokens.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&tokens, &mut _s);
        }
    }
    _s
}quote! {
25        #(#tokens)*
26    }))
27}
28
29fn derive_into_single_table(
30    item: &DeriveInput,
31    model: &Model,
32    table_name: &Path,
33) -> Result<TokenStream> {
34    let treat_none_as_default_value = model.treat_none_as_default_value();
35    let struct_name = &item.ident;
36
37    let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
38
39    let mut generate_borrowed_insert = true;
40
41    let mut direct_field_ty = Vec::with_capacity(model.fields().len());
42    let mut direct_field_assign = Vec::with_capacity(model.fields().len());
43    let mut ref_field_ty = Vec::with_capacity(model.fields().len());
44    let mut ref_field_assign = Vec::with_capacity(model.fields().len());
45
46    // Explicit trait bounds to improve error messages
47    let mut field_ty_bounds = Vec::with_capacity(model.fields().len());
48    let mut borrowed_field_ty_bounds = Vec::with_capacity(model.fields().len());
49    let mut field_ty_bounds_guard = HashMap::new();
50    let mut borrowed_field_ty_bounds_guard = HashMap::new();
51
52    for field in model.fields() {
53        // skip this field while generating the insertion
54        if field.skip_insertion() {
55            continue;
56        }
57        // Use field-level attr. with fallback to the struct-level one.
58        let treat_none_as_default_value = match &field.treat_none_as_default_value {
59            Some(attr) => {
60                if let Some(embed) = &field.embed {
61                    return Err(syn::Error::new(
62                        embed.attribute_span,
63                        "`embed` and `treat_none_as_default_value` are mutually exclusive",
64                    ));
65                }
66
67                if !is_option_ty(&field.ty) {
68                    return Err(syn::Error::new(
69                        field.ty.span(),
70                        "expected `treat_none_as_default_value` field to be of type `Option<_>`",
71                    ));
72                }
73
74                attr.item
75            }
76            None => treat_none_as_default_value,
77        };
78
79        match (field.serialize_as.as_ref(), field.embed()) {
80            (None, true) => {
81                direct_field_ty.push(field_ty_embed(field, None));
82                direct_field_assign.push(field_expr_embed(field, None));
83                ref_field_ty.push(field_ty_embed(field, Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'insert");
    _s
}quote!(&'insert))));
84                ref_field_assign.push(field_expr_embed(field, Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    _s
}quote!(&))));
85            }
86            (None, false) => {
87                direct_field_ty.push(field_ty(
88                    field,
89                    table_name,
90                    None,
91                    treat_none_as_default_value,
92                )?);
93                direct_field_assign.push(field_expr(
94                    field,
95                    table_name,
96                    None,
97                    treat_none_as_default_value,
98                )?);
99                ref_field_ty.push(field_ty(
100                    field,
101                    table_name,
102                    Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'insert");
    _s
}quote!(&'insert)),
103                    treat_none_as_default_value,
104                )?);
105                ref_field_assign.push(field_expr(
106                    field,
107                    table_name,
108                    Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    _s
}quote!(&)),
109                    treat_none_as_default_value,
110                )?);
111
112                field_ty_bounds.push(generate_field_bound(
113                    field,
114                    table_name,
115                    &field.ty,
116                    treat_none_as_default_value,
117                    None,
118                    &mut field_ty_bounds_guard,
119                )?);
120
121                borrowed_field_ty_bounds.push(generate_field_bound(
122                    field,
123                    table_name,
124                    &field.ty,
125                    treat_none_as_default_value,
126                    Some(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'insert");
        _s
    })parse_quote!('insert)),
127                    &mut borrowed_field_ty_bounds_guard,
128                )?);
129            }
130            (Some(AttributeSpanWrapper { item: ty, .. }), false) => {
131                direct_field_ty.push(field_ty_serialize_as(
132                    field,
133                    table_name,
134                    ty,
135                    treat_none_as_default_value,
136                )?);
137                direct_field_assign.push(field_expr_serialize_as(
138                    field,
139                    table_name,
140                    ty,
141                    treat_none_as_default_value,
142                )?);
143
144                field_ty_bounds.push(generate_field_bound(
145                    field,
146                    table_name,
147                    ty,
148                    treat_none_as_default_value,
149                    None,
150                    &mut field_ty_bounds_guard,
151                )?);
152
153                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
154            }
155            (Some(AttributeSpanWrapper { attribute_span, .. }), true) => {
156                return Err(syn::Error::new(
157                    *attribute_span,
158                    "`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`",
159                ));
160            }
161        }
162    }
163
164    let field_ty_bounds = field_ty_bounds
165        .into_iter()
166        .filter_map(|(type_to_check, bound)| {
167            filter_bounds(&field_ty_bounds_guard, type_to_check, bound)
168        });
169    let insert_owned = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "insertable");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Insertable");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "table");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&struct_name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "where");
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut field_ty_bounds, i) = field_ty_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let field_ty_bounds =
                match field_ty_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&field_ty_bounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "type");
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut direct_field_ty, i) =
                            direct_field_ty.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let direct_field_ty =
                                match direct_field_ty.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            ::quote::ToTokens::to_tokens(&direct_field_ty, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "as");
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "insertable");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Insertable");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&table_name, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_shr(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "values");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut direct_field_ty, i) =
                            direct_field_ty.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let direct_field_ty =
                                match direct_field_ty.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            ::quote::ToTokens::to_tokens(&direct_field_ty, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "as");
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "insertable");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Insertable");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&table_name, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_shr(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "diesel");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "insertable");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Insertable");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "table");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "values");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    {
                                        use ::quote::__private::ext::*;
                                        let has_iter = ::quote::__private::HasIterator::<false>;
                                        #[allow(unused_mut)]
                                        let (mut direct_field_assign, i) =
                                            direct_field_assign.quote_into_iter();
                                        let has_iter = has_iter | i;
                                        <_ as
                                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                                        while true {
                                            let direct_field_assign =
                                                match direct_field_assign.next() {
                                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                                    None => break,
                                                };
                                            ::quote::ToTokens::to_tokens(&direct_field_assign, &mut _s);
                                            ::quote::__private::push_comma(&mut _s);
                                        }
                                    }
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
170        impl #impl_generics diesel::insertable::Insertable<#table_name::table> for #struct_name #ty_generics
171        where
172            #where_clause
173            #(#field_ty_bounds,)*
174        {
175            type Values = <(#(#direct_field_ty,)*) as diesel::insertable::Insertable<#table_name::table>>::Values;
176
177            fn values(self) -> <(#(#direct_field_ty,)*) as diesel::insertable::Insertable<#table_name::table>>::Values {
178                diesel::insertable::Insertable::<#table_name::table>::values((#(#direct_field_assign,)*))
179            }
180        }
181    };
182
183    let insert_borrowed = if generate_borrowed_insert {
184        let mut impl_generics = item.generics.clone();
185        impl_generics.params.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'insert");
        _s
    })parse_quote!('insert));
186        let (impl_generics, ..) = impl_generics.split_for_impl();
187        let borrowed_field_ty_bounds =
188            borrowed_field_ty_bounds
189                .into_iter()
190                .filter_map(|(type_to_check, bound)| {
191                    filter_bounds(&borrowed_field_ty_bounds_guard, type_to_check, bound)
192                });
193
194        {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "insertable");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Insertable");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "table");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'insert");
    ::quote::ToTokens::to_tokens(&struct_name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "where");
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut borrowed_field_ty_bounds, i) =
            borrowed_field_ty_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let borrowed_field_ty_bounds =
                match borrowed_field_ty_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&borrowed_field_ty_bounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "type");
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut ref_field_ty, i) = ref_field_ty.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let ref_field_ty =
                                match ref_field_ty.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            ::quote::ToTokens::to_tokens(&ref_field_ty, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "as");
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "insertable");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Insertable");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&table_name, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_shr(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "values");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let has_iter = ::quote::__private::HasIterator::<false>;
                        #[allow(unused_mut)]
                        let (mut ref_field_ty, i) = ref_field_ty.quote_into_iter();
                        let has_iter = has_iter | i;
                        <_ as
                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                        while true {
                            let ref_field_ty =
                                match ref_field_ty.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            ::quote::ToTokens::to_tokens(&ref_field_ty, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "as");
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "insertable");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Insertable");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&table_name, &mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "table");
            ::quote::__private::push_shr(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Values");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "diesel");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "insertable");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Insertable");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "table");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "values");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    {
                                        use ::quote::__private::ext::*;
                                        let has_iter = ::quote::__private::HasIterator::<false>;
                                        #[allow(unused_mut)]
                                        let (mut ref_field_assign, i) =
                                            ref_field_assign.quote_into_iter();
                                        let has_iter = has_iter | i;
                                        <_ as
                                                ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                                        while true {
                                            let ref_field_assign =
                                                match ref_field_assign.next() {
                                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                                    None => break,
                                                };
                                            ::quote::ToTokens::to_tokens(&ref_field_assign, &mut _s);
                                            ::quote::__private::push_comma(&mut _s);
                                        }
                                    }
                                    _s
                                });
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
195            impl #impl_generics diesel::insertable::Insertable<#table_name::table>
196                for &'insert #struct_name #ty_generics
197            where
198                #where_clause
199                #(#borrowed_field_ty_bounds,)*
200            {
201                type Values = <(#(#ref_field_ty,)*) as diesel::insertable::Insertable<#table_name::table>>::Values;
202
203                fn values(self) -> <(#(#ref_field_ty,)*) as diesel::insertable::Insertable<#table_name::table>>::Values {
204                    diesel::insertable::Insertable::<#table_name::table>::values((#(#ref_field_assign,)*))
205                }
206            }
207        }
208    } else {
209        ::quote::__private::TokenStream::new();quote! {}
210    };
211
212    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&insert_owned, &mut _s);
    ::quote::ToTokens::to_tokens(&insert_borrowed, &mut _s);
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "internal");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "derives");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "insertable");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "UndecoratedInsertRecord");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "table");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&struct_name, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        ::quote::__private::TokenStream::new());
    _s
}quote! {
213        #insert_owned
214
215        #insert_borrowed
216
217        impl #impl_generics diesel::internal::derives::insertable::UndecoratedInsertRecord<#table_name::table>
218                for #struct_name #ty_generics
219            #where_clause
220        {
221        }
222    })
223}
224
225// this function exists to filter out bounds that are essentially the same but appear with different lifetimes.
226//
227// That's something that is not supported by rustc currently: https://github.com/rust-lang/rust/issues/21974
228// It might be fixed with the new trait solver which might land 2026
229pub fn filter_bounds(
230    guard: &HashMap<Type, HashSet<Vec<Lifetime>>>,
231    type_to_check: syn::Type,
232    bound: TokenStream,
233) -> Option<TokenStream> {
234    let count = guard
235        .get(&type_to_check)
236        .map(|t| t.len())
237        .unwrap_or_default();
238    (count <= 1).then_some(bound)
239}
240
241fn field_ty_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
242    let field_ty = &field.ty;
243    let span = Span::mixed_site().located_at(field.span);
244    {
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
    ::quote::ToTokens::to_tokens(&field_ty, &mut _s);
    _s
}quote_spanned!(span=> #lifetime #field_ty)
245}
246
247fn field_expr_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
248    let field_name = &field.name;
249    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
    ::quote::__private::push_ident(&mut _s, "self");
    ::quote::__private::push_dot(&mut _s);
    ::quote::ToTokens::to_tokens(&field_name, &mut _s);
    _s
}quote!(#lifetime self.#field_name)
250}
251
252fn field_ty_serialize_as(
253    field: &Field,
254    table_name: &Path,
255    ty: &Type,
256    treat_none_as_default_value: bool,
257) -> Result<TokenStream> {
258    let column_name = field.column_name()?.to_ident()?;
259    let span = Span::mixed_site().located_at(field.span);
260    if treat_none_as_default_value {
261        let inner_ty = inner_of_option_ty(ty);
262
263        Ok({
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident_spanned(&mut _s, _span, "std");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "option");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "dsl");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Eq");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::__private::push_shr_spanned(&mut _s, _span);
    _s
}quote_spanned! {span=>
264            std::option::Option<diesel::dsl::Eq<
265                #table_name::#column_name,
266                #inner_ty,
267            >>
268        })
269    } else {
270        Ok({
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "dsl");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Eq");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&ty, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::__private::push_gt_spanned(&mut _s, _span);
    _s
}quote_spanned! {span=>
271            diesel::dsl::Eq<
272                #table_name::#column_name,
273                #ty,
274            >
275        })
276    }
277}
278
279fn field_expr_serialize_as(
280    field: &Field,
281    table_name: &Path,
282    ty: &Type,
283    treat_none_as_default_value: bool,
284) -> Result<TokenStream> {
285    let field_name = &field.name;
286    let column_name = field.column_name()?.to_ident()?;
287    let column = {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    _s
}quote!(#table_name::#column_name);
288    if treat_none_as_default_value {
289        if is_option_ty(ty) {
290            Ok(
291                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "std");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "convert");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Into");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ty, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "into");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&field_name, &mut _s);
            _s
        });
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "map");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "v");
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "eq");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&column, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "v");
                    _s
                });
            _s
        });
    _s
}quote!(::std::convert::Into::<#ty>::into(self.#field_name).map(|v| diesel::ExpressionMethods::eq(#column, v))),
292            )
293        } else {
294            Ok(
295                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "std");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Some");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "eq");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&column, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "std");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "convert");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Into");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::ToTokens::to_tokens(&ty, &mut _s);
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "into");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "self");
                            ::quote::__private::push_dot(&mut _s);
                            ::quote::ToTokens::to_tokens(&field_name, &mut _s);
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote!(std::option::Option::Some(diesel::ExpressionMethods::eq(#column, ::std::convert::Into::<#ty>::into(self.#field_name)))),
296            )
297        }
298    } else {
299        Ok(
300            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "eq");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&column, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "std");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "convert");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Into");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&ty, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "into");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::ToTokens::to_tokens(&field_name, &mut _s);
                    _s
                });
            _s
        });
    _s
}quote!(diesel::ExpressionMethods::eq(#column, ::std::convert::Into::<#ty>::into(self.#field_name))),
301        )
302    }
303}
304
305fn field_ty(
306    field: &Field,
307    table_name: &Path,
308    lifetime: Option<TokenStream>,
309    treat_none_as_default_value: bool,
310) -> Result<TokenStream> {
311    let column_name = field.column_name()?.to_ident()?;
312    let span = Span::mixed_site().located_at(field.span);
313    if treat_none_as_default_value {
314        let inner_ty = inner_of_option_ty(&field.ty);
315
316        Ok({
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident_spanned(&mut _s, _span, "std");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "option");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "dsl");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Eq");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
    ::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::__private::push_shr_spanned(&mut _s, _span);
    _s
}quote_spanned! {span=>
317            std::option::Option<diesel::dsl::Eq<
318                #table_name::#column_name,
319                #lifetime #inner_ty,
320            >>
321        })
322    } else {
323        let inner_ty = &field.ty;
324
325        Ok({
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "dsl");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Eq");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
    ::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
    ::quote::__private::push_comma_spanned(&mut _s, _span);
    ::quote::__private::push_gt_spanned(&mut _s, _span);
    _s
}quote_spanned! {span=>
326            diesel::dsl::Eq<
327                #table_name::#column_name,
328                #lifetime #inner_ty,
329            >
330        })
331    }
332}
333
334fn field_expr(
335    field: &Field,
336    table_name: &Path,
337    lifetime: Option<TokenStream>,
338    treat_none_as_default_value: bool,
339) -> Result<TokenStream> {
340    let field_name = &field.name;
341    let column_name = field.column_name()?.to_ident()?;
342
343    let column: Expr = ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&table_name, &mut _s);
        ::quote::__private::push_colon2(&mut _s);
        ::quote::ToTokens::to_tokens(&column_name, &mut _s);
        _s
    })parse_quote!(#table_name::#column_name);
344    if treat_none_as_default_value {
345        if is_option_ty(&field.ty) {
346            if lifetime.is_some() {
347                Ok(
348                    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "self");
    ::quote::__private::push_dot(&mut _s);
    ::quote::ToTokens::to_tokens(&field_name, &mut _s);
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "as_ref");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        ::quote::__private::TokenStream::new());
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "map");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "x");
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "eq");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&column, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "x");
                    _s
                });
            _s
        });
    _s
}quote!(self.#field_name.as_ref().map(|x| diesel::ExpressionMethods::eq(#column, x))),
349                )
350            } else {
351                Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "self");
    ::quote::__private::push_dot(&mut _s);
    ::quote::ToTokens::to_tokens(&field_name, &mut _s);
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "map");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "x");
            ::quote::__private::push_or(&mut _s);
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "eq");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&column, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "x");
                    _s
                });
            _s
        });
    _s
}quote!(self.#field_name.map(|x| diesel::ExpressionMethods::eq(#column, x))))
352            }
353        } else {
354            Ok(
355                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "std");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Option");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Some");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "eq");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::ToTokens::to_tokens(&column, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_dot(&mut _s);
                    ::quote::ToTokens::to_tokens(&field_name, &mut _s);
                    _s
                });
            _s
        });
    _s
}quote!(std::option::Option::Some(diesel::ExpressionMethods::eq(#column, #lifetime self.#field_name))),
356            )
357        }
358    } else {
359        Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ExpressionMethods");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "eq");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&column, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&lifetime, &mut _s);
            ::quote::__private::push_ident(&mut _s, "self");
            ::quote::__private::push_dot(&mut _s);
            ::quote::ToTokens::to_tokens(&field_name, &mut _s);
            _s
        });
    _s
}quote!(diesel::ExpressionMethods::eq(#column, #lifetime self.#field_name)))
360    }
361}
362
363/// Generate explicit trait bound with field span to improve error messages
364pub(crate) fn generate_field_bound(
365    field: &Field,
366    table_name: &Path,
367    ty: &Type,
368    treat_none_as_default_value: bool,
369    borrowed: Option<Lifetime>,
370    guard: &mut HashMap<Type, HashSet<Vec<Lifetime>>>,
371) -> Result<(syn::Type, TokenStream)> {
372    let column_name = field.column_name()?.to_ident()?;
373    let span = Span::mixed_site().located_at(field.span);
374    let ty_to_check = if treat_none_as_default_value {
375        inner_of_option_ty(ty)
376    } else {
377        ty
378    };
379    let mut type_for_guard = ty_to_check.clone();
380    // we use syn::visit_mut here to:
381    // * Collect all lifetimes that appear in a certain type
382    // * Normalize all lifetimes appearing in a certain type to 'static to be able
383    // to use the type as key for a hashmap to find out if the type already appeared in
384    // another bound. The value in the hashmap then contains all the different lifetime
385    // variants, which lets us reason about whether there are different variants or not.
386    let mut collector = LifetimeCollector::default();
387    syn::visit_mut::visit_type_mut(&mut collector, &mut type_for_guard);
388    let life_times = collector.lifetimes;
389
390    guard
391        .entry(type_for_guard.clone())
392        .or_default()
393        .insert(life_times);
394    let bound_ty = if let Some(lt) = borrowed {
395        {
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&lt, &mut _s);
    ::quote::ToTokens::to_tokens(&ty_to_check, &mut _s);
    _s
}quote_spanned! {span=> &#lt #ty_to_check}
396    } else {
397        {
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&ty_to_check, &mut _s);
    _s
}quote_spanned! {span=> #ty_to_check}
398    };
399    let bound = {
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&bound_ty, &mut _s);
    ::quote::__private::push_colon_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "expression");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "AsExpression");
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::__private::push_lt_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&table_name, &mut _s);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::ToTokens::to_tokens(&column_name, &mut _s);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "as");
    ::quote::__private::push_ident_spanned(&mut _s, _span, "diesel");
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "Expression");
    ::quote::__private::push_gt_spanned(&mut _s, _span);
    ::quote::__private::push_colon2_spanned(&mut _s, _span);
    ::quote::__private::push_ident_spanned(&mut _s, _span, "SqlType");
    ::quote::__private::push_gt_spanned(&mut _s, _span);
    _s
}quote_spanned! {span=>
400        #bound_ty: diesel::expression::AsExpression<
401            <#table_name::#column_name as diesel::Expression>::SqlType
402        >
403    };
404    Ok((type_for_guard, bound))
405}
406
407#[derive(#[automatically_derived]
impl ::core::default::Default for LifetimeCollector {
    #[inline]
    fn default() -> LifetimeCollector {
        LifetimeCollector { lifetimes: ::core::default::Default::default() }
    }
}Default)]
408struct LifetimeCollector {
409    lifetimes: Vec<Lifetime>,
410}
411
412impl syn::visit_mut::VisitMut for LifetimeCollector {
413    fn visit_lifetime_mut(&mut self, i: &mut syn::Lifetime) {
414        self.lifetimes
415            .push(std::mem::replace(i, ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_lifetime(&mut _s, "\'static");
        _s
    })syn::parse_quote!('static)));
416
417        syn::visit_mut::visit_lifetime_mut(self, i);
418    }
419}