Skip to main content

yoke_derive/
lib.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
6// #![cfg_attr(not(any(test, doc)), no_std)]
7#![cfg_attr(
8    not(test),
9    deny(
10        clippy::indexing_slicing,
11        clippy::unwrap_used,
12        clippy::expect_used,
13        clippy::panic,
14    )
15)]
16#![warn(missing_docs)]
17
18//! Custom derives for `Yokeable` from the `yoke` crate.
19
20mod lifetimes;
21mod visitor;
22
23use proc_macro::TokenStream;
24use proc_macro2::TokenStream as TokenStream2;
25use quote::quote;
26use syn::ext::IdentExt as _;
27use syn::spanned::Spanned;
28use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam, Ident, WherePredicate};
29use synstructure::Structure;
30
31use self::lifetimes::{custom_lt, ignored_lifetime_ident, replace_lifetime, static_lt};
32use self::visitor::{
33    check_parameter_for_bound_lts, check_type_for_parameters, check_where_clause_for_bound_lts,
34    CheckResult,
35};
36
37/// Custom derive for `yoke::Yokeable`.
38///
39/// If your struct contains `zerovec::ZeroMap`, then the compiler will not
40/// be able to guarantee the lifetime covariance due to the generic types on
41/// the `ZeroMap` itself. You must add the following attribute in order for
42/// the custom derive to work with `ZeroMap`.
43///
44/// ```rust,ignore
45/// #[derive(Yokeable)]
46/// #[yoke(prove_covariance_manually)]
47/// ```
48///
49/// Beyond this case, if the derive fails to compile due to lifetime issues, it likely
50/// means that the lifetime is not covariant and `Yokeable` is not safe to implement.
51#[proc_macro_derive(Yokeable, attributes(yoke))]
52pub fn yokeable_derive(input: TokenStream) -> TokenStream {
53    let input = match ::syn::parse::<DeriveInput>(input) {
    ::syn::__private::Ok(data) => data,
    ::syn::__private::Err(err) => {
        return ::syn::__private::TokenStream::from(err.to_compile_error());
    }
}parse_macro_input!(input as DeriveInput);
54    TokenStream::from(yokeable_derive_impl(&input))
55}
56
57/// A small amount of metadata about a field of the yokeable type
58struct FieldParamUsage {
59    uses_lt: bool,
60    uses_ty: bool,
61}
62
63impl From<CheckResult> for FieldParamUsage {
64    fn from(value: CheckResult) -> Self {
65        Self {
66            uses_lt: value.uses_lifetime_param,
67            uses_ty: value.uses_type_params,
68        }
69    }
70}
71
72fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
73    let name = &input.ident;
74    let tybounds = input
75        .generics
76        .params
77        .iter()
78        .filter_map(|param| {
79            match param {
80                GenericParam::Lifetime(_) => None,
81                GenericParam::Type(ty) => {
82                    // Strip out param defaults, we don't need them in the impl
83                    let mut ty = ty.clone();
84                    ty.eq_token = None;
85                    ty.default = None;
86                    Some(GenericParam::Type(ty))
87                }
88                // TODO: support const-generics in a future PR
89                // GenericParam::Const(const_param) => {
90                //     // Strip out param defaults, we don't need them in the impl
91                //     let mut const_param = const_param.clone();
92                //     const_param.eq_token = None;
93                //     const_param.default = None;
94                //     Some(GenericParam::Const(const_param))
95                // }
96                GenericParam::Const(_) => None,
97            }
98        })
99        .collect::<Vec<_>>();
100    let typarams = tybounds
101        .iter()
102        .map(|param| match param {
103            // We filtered out lifetime parameters
104            GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
105            GenericParam::Type(ty) => ty.ident.clone(),
106            // TODO: support const-generics in a future PR
107            // GenericParam::Const(const_param) => const_param.ident.clone(),
108            GenericParam::Const(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
109        })
110        .collect::<Vec<_>>();
111    let wherebounds = input
112        .generics
113        .where_clause
114        .iter()
115        .flat_map(|wc| wc.predicates.iter())
116        // If some future version of Rust adds more than just lifetime and type where-bound
117        // predicates, we may want to match more predicates.
118        .filter(|p| #[allow(non_exhaustive_omitted_patterns)] match p {
    WherePredicate::Type(_) => true,
    _ => false,
}matches!(p, WherePredicate::Type(_)))
119        .collect::<Vec<_>>();
120    // We require all type parameters be 'static, otherwise
121    // the Yokeable impl becomes really unwieldy to generate safely.
122    let static_bounds: Vec<WherePredicate> = tybounds
123        .iter()
124        .filter_map(|param| {
125            if let GenericParam::Type(ty) = param {
126                let ty = &ty.ident;
127                Some(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&ty, &mut _s);
        ::quote::__private::push_colon(&mut _s);
        ::quote::__private::push_lifetime(&mut _s, "\'static");
        _s
    })parse_quote!(#ty: 'static))
128            } else {
129                None
130            }
131        })
132        .collect();
133    // Above idents are *not* `unraw`d, because they may be emitted by the derive
134    // (so they might actually need to be raw).
135
136    // Either the `unraw`d first lifetime parameter of the yokeable, or some ignored ident.
137    // This parameter affects `uses_lifetime_param` values of `CheckResult`s and `uses_lt`
138    // values of `FieldParamUsage`, but those values only impact the generated code if there
139    // is at least one lifetime parameter; therefore, the random ident doesn't matter.
140    let lt_param = input
141        .generics
142        .lifetimes()
143        .next()
144        .map_or_else(ignored_lifetime_ident, |lt| lt.lifetime.ident.unraw());
145    let typarams_env = tybounds
146        .iter()
147        .filter_map(|param| {
148            if let GenericParam::Type(ty) = param {
149                Some(ty.ident.unraw())
150            } else {
151                None
152            }
153        })
154        .collect();
155    let mut underscores_for_lt = 0;
156
157    // We need to do this analysis even before the case where there are zero lifetime parameters
158    // in order to choose a `'__[underscores]__yoke` lifetime.
159    // We need to check:
160    // - trait bounds on generic type parameters
161    // - default types for generic type parameters
162    // - type bounds on const generic parameters
163    // - where-bounds
164    // - field types
165    // Checking lifetime parameters and default values for const generic parameters isn't
166    // particularly useful, but does no harm, so the simplest approach to knock out the first three
167    // is to just check every parameter.
168    for param in &input.generics.params {
169        underscores_for_lt = underscores_for_lt.max(check_parameter_for_bound_lts(param));
170    }
171    if let Some(where_clause) = &input.generics.where_clause {
172        underscores_for_lt = underscores_for_lt.max(check_where_clause_for_bound_lts(where_clause));
173    }
174
175    let structure = {
176        let mut structure = Structure::new(input);
177        structure.bind_with(|_| synstructure::BindStyle::Move);
178        structure
179    };
180
181    // Information from `synstructure::Structure`, whose ordering of fields is deterministic.
182    // Note that it's crucial that we don't filter out any variants or fields from the `Structure`.
183    let mut field_info: Vec<FieldParamUsage> = Vec::new();
184    // This code creating `field_info` should not be carelessly modified, else it could cause
185    // a panic in a below `expect`.
186    for variant_info in structure.variants() {
187        for field_binding_info in variant_info.bindings() {
188            let field = field_binding_info.ast();
189            // Note: `lt_param` and everything in `typarams_env` were `unraw`d
190            let check_result = check_type_for_parameters(&lt_param, &typarams_env, &field.ty);
191
192            underscores_for_lt = underscores_for_lt.max(check_result.min_underscores_for_yoke_lt);
193            field_info.push(check_result.into());
194        }
195    }
196    let field_info = field_info;
197
198    // All usages of the `check_*` functions are above this point,
199    // in order to ensure that `yoke_lt` is correct.
200    let (yoke_lt, bound_lt) = {
201        let underscores = ::alloc::vec::from_elem(b'_', underscores_for_lt)vec![b'_'; underscores_for_lt];
202        #[expect(clippy::expect_used, reason = "invariant is ensured immediately above")]
203        let underscores = core::str::from_utf8(&underscores).expect("_ is ASCII and thus UTF-8");
204        (
205            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\'{0}yoke", underscores))
    })format!("'{underscores}yoke"),
206            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\'_{0}yoke", underscores))
    })format!("'_{underscores}yoke"),
207        )
208    };
209    // This is used where the `Yokeable<'a>` trait uses `'a` by default
210    let yoke_lt = custom_lt(&yoke_lt);
211    // This is used where the `Yokeable<'a>` trait uses `'b` by default
212    let bound_lt = custom_lt(&bound_lt);
213
214    let mut lts = input.generics.lifetimes();
215
216    if lts.next().is_none() {
217        // There are 0 lifetime parameters.
218
219        return {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut tybounds, i) = tybounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let tybounds =
                match tybounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&tybounds, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "yoke");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Yokeable");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::__private::push_lt(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut typarams, i) = typarams.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let typarams =
                match typarams.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&typarams, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "where");
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut static_bounds, i) = static_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let static_bounds =
                match static_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&static_bounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut wherebounds, i) = wherebounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let wherebounds =
                match wherebounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&wherebounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    ::quote::__private::push_ident(&mut _s, "Self");
    ::quote::__private::push_colon(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Sized");
    ::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, "Output");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_owned");
            ::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_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "make");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "this");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "this");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_mut");
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "F");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "where");
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_lifetime(&mut _s, "\'static");
            ::quote::__private::push_add(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "FnOnce");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::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
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
220            // This is safe because there are no lifetime parameters, and `type Output = Self`.
221            unsafe impl<#yoke_lt, #(#tybounds),*> yoke::Yokeable<#yoke_lt>
222            for #name<#(#typarams),*>
223            where
224                #(#static_bounds,)*
225                #(#wherebounds,)*
226                Self: Sized
227            {
228                type Output = Self;
229                #[inline]
230                fn transform(&self) -> &Self::Output {
231                    self
232                }
233                #[inline]
234                fn transform_owned(self) -> Self::Output {
235                    self
236                }
237                #[inline]
238                unsafe fn make(this: Self::Output) -> Self {
239                    this
240                }
241                #[inline]
242                fn transform_mut<F>(&#yoke_lt mut self, f: F)
243                where
244                    F: 'static + for<#bound_lt> FnOnce(&#bound_lt mut Self::Output) {
245                    f(self)
246                }
247            }
248        };
249    };
250
251    if lts.next().is_some() {
252        // We already extracted one lifetime into `source_lt`, so this means there are
253        // multiple lifetimes.
254        return syn::Error::new(
255            input.generics.span(),
256            "derive(Yokeable) cannot have multiple lifetime parameters",
257        )
258        .to_compile_error();
259    }
260
261    let manual_covariance = input.attrs.iter().any(|a| {
262        if a.path().is_ident("yoke") {
263            if let Ok(i) = a.parse_args::<Ident>() {
264                if i == "prove_covariance_manually" {
265                    return true;
266                }
267            }
268        }
269        false
270    });
271
272    if !manual_covariance {
273        // This is safe because as long as `transform()` compiles,
274        // we can be sure that `'a` is a covariant lifetime on `Self`.
275        // (Using `'a` as shorthand for `#yoke_lt`.)
276        //
277        // In particular, the operand of `&raw const` is not a location where implicit
278        // type coercion can occur, so the type of `&raw const self` is `*const &'a Self`.
279        // The RHS of a `let` with an explicit type annotation allows type coercion, so
280        // `transform` checks that `*const &'a Self` can coerce to `*const &'a Self::Output`.
281        // Most of the possible type coercions
282        // (listed at https://doc.rust-lang.org/reference/type-coercions.html)
283        // do not apply, other than subtyping coercions and transitive coercions (which do
284        // not add anything beyond subtyping coercions). In particular, there's nothing
285        // like a `DerefRaw` on `*const T`, and `&T` does not implement `Unsize`, so
286        // there cannot be an unsizing coercion from `*const &'a Self` to
287        // `*const &'a Self::Output`. Therefore, `transform` compiles if and only if
288        // a subtyping coercion is possible; this requires that `Self` must be a subtype
289        // of `Self::Output`, just as `&'static T` is a subtype of `&'a T` (for `T: 'static`).
290        // This ensures covariance.
291        //
292        // This will not work for structs involving ZeroMap since
293        // the compiler does not know that ZeroMap is covariant.
294        //
295        // This custom derive can be improved to handle this case when necessary,
296        // with `prove_covariance_manually`.
297        return {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut tybounds, i) = tybounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let tybounds =
                match tybounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&tybounds, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "yoke");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Yokeable");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'static");
    ::quote::__private::push_comma(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut typarams, i) = typarams.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let typarams =
                match typarams.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&typarams, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "where");
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut static_bounds, i) = static_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let static_bounds =
                match static_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&static_bounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut wherebounds, i) = wherebounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let wherebounds =
                match wherebounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&wherebounds, &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, "Output");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            {
                use ::quote::__private::ext::*;
                let mut _first = true;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut typarams, i) = typarams.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let typarams =
                        match typarams.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    if !_first { ::quote::__private::push_comma(&mut _s); }
                    _first = false;
                    ::quote::ToTokens::to_tokens(&typarams, &mut _s);
                }
            }
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_and(&mut _s);
            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "if");
                    ::quote::__private::push_ident(&mut _s, "false");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "let");
                            ::quote::__private::push_underscore(&mut _s);
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::__private::push_star(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "const");
                            ::quote::__private::push_and(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Output");
                            ::quote::__private::push_eq(&mut _s);
                            ::quote::__private::push_and(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "raw");
                            ::quote::__private::push_ident(&mut _s, "const");
                            ::quote::__private::push_ident(&mut _s, "self");
                            ::quote::__private::push_semi(&mut _s);
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_owned");
            ::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_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "make");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "from");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "core");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "mem");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "transmute");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_lt(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_gt(&mut _s);
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "from");
                            _s
                        });
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_mut");
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "F");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "where");
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_lifetime(&mut _s, "\'static");
            ::quote::__private::push_add(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "FnOnce");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "let");
                    ::quote::__private::push_ident(&mut _s, "y");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_and(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mut");
                            ::quote::__private::push_star(&mut _s);
                            ::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_ident(&mut _s, "as");
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "mut");
                                    ::quote::__private::push_ident(&mut _s, "Self");
                                    ::quote::__private::push_ident(&mut _s, "as");
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "mut");
                                    ::quote::__private::push_ident(&mut _s, "Self");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Output");
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "y");
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
298            unsafe impl<#yoke_lt, #(#tybounds),*> yoke::Yokeable<#yoke_lt>
299            for #name<'static, #(#typarams),*>
300            where
301                #(#static_bounds,)*
302                #(#wherebounds,)*
303                // Adding `Self: Sized` here doesn't work.
304                // `for<#bound_lt> #name<#bound_lt, #(#typarams),*>: Sized`
305                // might work, though. Since these trait bounds are very finicky, it's best to just
306                // not try unless necessary.
307            {
308                type Output = #name<#yoke_lt, #(#typarams),*>;
309                #[inline]
310                fn transform(&#yoke_lt self) -> &#yoke_lt Self::Output {
311                    if false {
312                        let _: *const &#yoke_lt Self::Output = &raw const self;
313                    }
314                    self
315                }
316                #[inline]
317                fn transform_owned(self) -> Self::Output {
318                    self
319                }
320                #[inline]
321                unsafe fn make(from: Self::Output) -> Self {
322                    ::core::mem::transmute::<Self::Output, Self>(from)
323                }
324                #[inline]
325                fn transform_mut<F>(&#yoke_lt mut self, f: F)
326                where
327                    F: 'static + for<#bound_lt> FnOnce(&#bound_lt mut Self::Output) {
328                    let y = unsafe { &mut *(self as *mut Self as *mut Self::Output) };
329                    f(y)
330                }
331            }
332        };
333    }
334
335    // `prove_covariance_manually` requires additional bounds
336    let mut manual_proof_bounds: Vec<WherePredicate> = Vec::new();
337    let mut yokeable_checks = TokenStream2::new();
338    let mut output_checks = TokenStream2::new();
339    let mut field_info = field_info.into_iter();
340
341    // See `synstructure::Structure::each` and `synstructure::VariantInfo::each`
342    // for the setup of the two `*_checks` token streams. We can elide some brackets compared
343    // to `synstructure`, since we know that each check defines no local variables, items, etc.
344
345    // We iterate over the fields of `structure` in the same way that `field_info` was created.
346    for variant_info in structure.variants() {
347        let mut yokeable_check_body = TokenStream2::new();
348        let mut output_check_body = TokenStream2::new();
349
350        for field_binding_info in variant_info.bindings() {
351            let field = field_binding_info.ast();
352            let field_binding = &field_binding_info.binding;
353
354            // This invariant is somewhat complicated, but immutable variables, iteration order,
355            // and creating/using one `FieldParamUsage per iteration ensure that `field_info`
356            // has an entry for this field (and it refers to the expected field).
357            #[expect(
358                clippy::expect_used,
359                reason = "See above comment; this should never panic"
360            )]
361            let FieldParamUsage { uses_lt, uses_ty } = field_info
362                .next()
363                .expect("fields of an unmutated synstructure::Structure should remain the same");
364
365            // Note that this type could be a weird non-pure macro type. However, even though
366            // we evaluate it once or twice in where-bounds, we evaluate it exactly once
367            // in the soundness-critical checks, so it can't cause UB by unexpectedly evaluating
368            // to a different type. That can only cause a compile error at worst.
369            let fty_static = replace_lifetime(&lt_param, &field.ty, static_lt());
370
371            // For field types that don't use type or lifetime parameters, we don't add `Yokeable`
372            // or `'static` where-bounds, and the field is required to unconditionally meet a
373            // `'static` requirement (in its output form).
374            //
375            // For field types that use the lifetime parameter but no type parameters, we also don't
376            // add any where-bounds, and the field is required to unconditionally meet a
377            // `Yokeable` requirement (in its static yokeable form).
378            // (The compiler should be able to figure out whether that requirement is satisfied.
379            // A where-bound is intentionally avoided, to avoid letting `derive(Yokeable)`
380            // compile on a struct when it's statically known that the where-bound is never
381            // satisfied.)
382            //
383            // For field types that use a type parameter but not the lifetime parameter, the field
384            // is assumed not to borrow from the cart and is therefore required to be `'static`
385            // (in its output form), and a where-bound is added for this field being `'static`.
386            //
387            // For field types that use both the lifetime parameter and type parameters, the
388            // field is required to be `Yokeable` (in its static form). Since there may be complex
389            // preconditions to `FieldTy: Yokeable` that need to be satisfied, a where-bound
390            // requires that `FieldTy<'static>: Yokeable<#yoke_lt, Output = FieldTy<#yoke_lt>>`.
391            // This requirement is also tested on the field's static yokeable form.
392
393            // Note: if `field.ty` involves a non-pure macro type, each time it's evaluated, it
394            // could be a different type. The where-bounds are relied on to make the impl compile
395            // in sane cases, *not* for soundness. Our `transform()` impl does not blindly assume
396            // that the fields' types implement `Yokeable` or `'static`, regardless of these bounds.
397            if uses_ty {
398                if uses_lt {
399                    let fty_output = replace_lifetime(&lt_param, &field.ty, yoke_lt.clone());
400
401                    manual_proof_bounds.push(
402                        ::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&fty_static, &mut _s);
        ::quote::__private::push_colon(&mut _s);
        ::quote::__private::push_ident(&mut _s, "yoke");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Yokeable");
        ::quote::__private::push_lt(&mut _s);
        ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
        ::quote::__private::push_comma(&mut _s);
        ::quote::__private::push_ident(&mut _s, "Output");
        ::quote::__private::push_eq(&mut _s);
        ::quote::ToTokens::to_tokens(&fty_output, &mut _s);
        ::quote::__private::push_gt(&mut _s);
        _s
    })parse_quote!(#fty_static: yoke::Yokeable<#yoke_lt, Output = #fty_output>),
403                    );
404                } else {
405                    manual_proof_bounds.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&fty_static, &mut _s);
        ::quote::__private::push_colon(&mut _s);
        ::quote::__private::push_lifetime(&mut _s, "\'static");
        _s
    })parse_quote!(#fty_static: 'static));
406                }
407            }
408            if uses_lt {
409                // This confirms that this `FieldTy` is a subtype of something which implements
410                // `Yokeable<'a>`, and since only `'static` types can be subtypes of a `'static`
411                // type (and all `Yokeable` implementors are `'static`), we have that either:
412                // - `FieldTy` is some `'static` type which does NOT implement `Yokeable`, but via
413                //   function pointer subtyping or something similar, is a subtype of something
414                //   implementing `Yokeable`, or
415                // - `FieldTy` is some type which does itself implement `Yokeable`.
416                // In either of those cases, it is sound to treat `FieldTy` as covariant in the `'a`
417                // parameter. (Using `'a` as shorthand for `#yoke_lt`.)
418                //
419                // Now, to justify that `FieldTy` (the field's actual type,
420                // not just `field.ty`, which may have a non-pure macro type)
421                // is a subtype of something which implements `Yokeable<'a>`:
422                //
423                // `#field_binding` has type `&'a FieldTy` (since it's a field of `&'a Self` matched
424                // as `self`). The operand of `&raw const` is not a location where implicit type
425                // coercion can occur. Therefore, `&raw const #field_binding` is guaranteed to be
426                // type `*const &'a FieldTy`. The argument to `__yoke_derive_require_yokeable`
427                // does allow type coercion.
428                // Looking at <https://doc.rust-lang.org/reference/type-coercions.html>,
429                // there are only three types of coercions that could plausibly apply:
430                // - subtyping coercions,
431                // - transitive coercions, and
432                // - unsizing coercions.
433                // (If some sort of `DerefRaw` trait gets added for `*const`, there could plausibly
434                // be problems with that. But there's no reason to think that such a trait will be
435                // added, since it'd mess with `unsafe` code, and Rust devs should recognize that.)
436                //
437                // Since `&'a _` does not implement `Unsize`, we have that `*const &'a _` does not
438                // allow an unsizing coercion to occur. Therefore, there are only subtyping
439                // coercions, since transitive coercions add nothing on top of subtyping coercions.
440                // Therefore, if this compiles, `*const &'a FieldTy` must be a subtype of
441                // `*const &'a T` where `T = #fty_static` is the generic parameter of
442                // `__yoke_derive_require_yokeable`.
443                // Looking at the signature of that function generated below, we have that
444                // `T: Yokeable<'a>` (if it compiles). Note that if `#fty_static` is incorrect,
445                // even if there is some other `T` which would work, this will just fail to compile.
446                // Since `*const _` and `&'a _` are covariant over their type parameters, we have
447                // that `FieldTy` must be a subtype of `T` in order for a subtyping coercion from
448                // `*const &'a FieldTy` to `*const &'a T` to occur.
449                //
450                // Therefore, `FieldTy` must be a subtype of something which implements
451                // `Yokeable<'a>` in order for this to compile. (Though that is not a _sufficient_
452                // condition to compile, as some weird macro type could break stuff.)
453                yokeable_check_body.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "__yoke_derive_require_yokeable");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&fty_static, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "raw");
            ::quote::__private::push_ident(&mut _s, "const");
            ::quote::ToTokens::to_tokens(&field_binding, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
454                    __yoke_derive_require_yokeable::<#yoke_lt, #fty_static>(&raw const #field_binding);
455                });
456            } else {
457                // No visible nested lifetimes, so there should be nothing to be done in sane cases.
458                // However, in case a macro type does something strange and accesses the available
459                // `#yoke_lt` lifetime, we still need to check that the field's actual type is
460                // `'static` regardless of `#yoke_lt` (which we can check by ensuring that it
461                // be a subtype of a `'static` type).
462                // See reasoning in the `if` branch for why this works. The difference is that
463                // `FieldTy` is guaranteed to be a subtype of `T = #fty_static` where `T: 'static`
464                // (if this compiles). Since the field's type is a subtype of something which is
465                // `'static`, it must itself be `'static`, and therefore did not manage to use
466                // `#yoke_lt` via a macro.
467                // Note that creating and using `#fty_output` is not necessary here, since
468                // `field.ty == fty_static == fty_output` (no lifetime was visibly present which
469                // could be replaced).
470                output_check_body.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "__yoke_derive_require_static");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    ::quote::ToTokens::to_tokens(&fty_static, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_and(&mut _s);
            ::quote::__private::push_ident(&mut _s, "raw");
            ::quote::__private::push_ident(&mut _s, "const");
            ::quote::ToTokens::to_tokens(&field_binding, &mut _s);
            _s
        });
    ::quote::__private::push_semi(&mut _s);
    _s
}quote! {
471                    __yoke_derive_require_static::<#yoke_lt, #fty_static>(&raw const #field_binding);
472                });
473            }
474        }
475
476        let pat = variant_info.pat();
477        yokeable_checks.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&pat, &mut _s);
    ::quote::__private::push_fat_arrow(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&yokeable_check_body, &mut _s);
            _s
        });
    _s
}quote! { #pat => { #yokeable_check_body }});
478        output_checks.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::ToTokens::to_tokens(&pat, &mut _s);
    ::quote::__private::push_fat_arrow(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&output_check_body, &mut _s);
            _s
        });
    _s
}quote! { #pat => { #output_check_body }});
479    }
480
481    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "unsafe");
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_comma(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut tybounds, i) = tybounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let tybounds =
                match tybounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&tybounds, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "yoke");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Yokeable");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&name, &mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'static");
    ::quote::__private::push_comma(&mut _s);
    {
        use ::quote::__private::ext::*;
        let mut _first = true;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut typarams, i) = typarams.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let typarams =
                match typarams.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            if !_first { ::quote::__private::push_comma(&mut _s); }
            _first = false;
            ::quote::ToTokens::to_tokens(&typarams, &mut _s);
        }
    }
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "where");
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut static_bounds, i) = static_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let static_bounds =
                match static_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&static_bounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut wherebounds, i) = wherebounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let wherebounds =
                match wherebounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&wherebounds, &mut _s);
            ::quote::__private::push_comma(&mut _s);
        }
    }
    {
        use ::quote::__private::ext::*;
        let has_iter = ::quote::__private::HasIterator::<false>;
        #[allow(unused_mut)]
        let (mut manual_proof_bounds, i) =
            manual_proof_bounds.quote_into_iter();
        let has_iter = has_iter | i;
        <_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
        while true {
            let manual_proof_bounds =
                match manual_proof_bounds.next() {
                    Some(_x) => ::quote::__private::RepInterp(_x),
                    None => break,
                };
            ::quote::ToTokens::to_tokens(&manual_proof_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, "Output");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&name, &mut _s);
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
            ::quote::__private::push_comma(&mut _s);
            {
                use ::quote::__private::ext::*;
                let mut _first = true;
                let has_iter = ::quote::__private::HasIterator::<false>;
                #[allow(unused_mut)]
                let (mut typarams, i) = typarams.quote_into_iter();
                let has_iter = has_iter | i;
                <_ as
                        ::quote::__private::CheckHasIterator<true>>::check(has_iter);
                while true {
                    let typarams =
                        match typarams.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    if !_first { ::quote::__private::push_comma(&mut _s); }
                    _first = false;
                    ::quote::ToTokens::to_tokens(&typarams, &mut _s);
                }
            }
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_semi(&mut _s);
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "self");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_and(&mut _s);
            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "if");
                    ::quote::__private::push_ident(&mut _s, "false");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_pound(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Bracket,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "allow");
                                    ::quote::__private::push_group(&mut _s,
                                        ::quote::__private::Delimiter::Parenthesis,
                                        {
                                            let mut _s = ::quote::__private::TokenStream::new();
                                            ::quote::__private::push_ident(&mut _s, "dead_code");
                                            _s
                                        });
                                    _s
                                });
                            ::quote::__private::push_ident(&mut _s, "fn");
                            ::quote::__private::push_ident(&mut _s,
                                "__yoke_derive_require_yokeable");
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "T");
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "yoke");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Yokeable");
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "_t");
                                    ::quote::__private::push_colon(&mut _s);
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "const");
                                    ::quote::__private::push_and(&mut _s);
                                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                                    ::quote::__private::push_ident(&mut _s, "T");
                                    _s
                                });
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                ::quote::__private::TokenStream::new());
                            ::quote::__private::push_ident(&mut _s, "match");
                            ::quote::__private::push_ident(&mut _s, "self");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::ToTokens::to_tokens(&yokeable_checks, &mut _s);
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s, "let");
                    ::quote::__private::push_ident(&mut _s, "output");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mem");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "transmute");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::__private::push_and(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_and(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Output");
                            ::quote::__private::push_gt(&mut _s);
                            ::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
                                });
                            _s
                        });
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "if");
                    ::quote::__private::push_ident(&mut _s, "false");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_pound(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Bracket,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "allow");
                                    ::quote::__private::push_group(&mut _s,
                                        ::quote::__private::Delimiter::Parenthesis,
                                        {
                                            let mut _s = ::quote::__private::TokenStream::new();
                                            ::quote::__private::push_ident(&mut _s, "dead_code");
                                            _s
                                        });
                                    _s
                                });
                            ::quote::__private::push_ident(&mut _s, "fn");
                            ::quote::__private::push_ident(&mut _s,
                                "__yoke_derive_require_static");
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "T");
                            ::quote::__private::push_colon(&mut _s);
                            ::quote::__private::push_lifetime(&mut _s, "\'static");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "_t");
                                    ::quote::__private::push_colon(&mut _s);
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "const");
                                    ::quote::__private::push_and(&mut _s);
                                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                                    ::quote::__private::push_ident(&mut _s, "T");
                                    _s
                                });
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                ::quote::__private::TokenStream::new());
                            ::quote::__private::push_ident(&mut _s, "match");
                            ::quote::__private::push_ident(&mut _s, "output");
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Brace,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::ToTokens::to_tokens(&output_checks, &mut _s);
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_ident(&mut _s, "output");
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_owned");
            ::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_ident(&mut _s, "Self");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Output");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mem");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "transmute");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Output");
                            ::quote::__private::push_gt(&mut _s);
                            ::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
                                });
                            _s
                        });
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "unsafe");
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "make");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "from");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_rarrow(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Self");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "core");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mem");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "transmute");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_lt(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_colon2(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Output");
                            ::quote::__private::push_comma(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "Self");
                            ::quote::__private::push_gt(&mut _s);
                            ::quote::__private::push_group(&mut _s,
                                ::quote::__private::Delimiter::Parenthesis,
                                {
                                    let mut _s = ::quote::__private::TokenStream::new();
                                    ::quote::__private::push_ident(&mut _s, "from");
                                    _s
                                });
                            _s
                        });
                    _s
                });
            ::quote::__private::push_pound(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Bracket,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "inline");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "fn");
            ::quote::__private::push_ident(&mut _s, "transform_mut");
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&yoke_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "self");
                    ::quote::__private::push_comma(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::quote::__private::push_colon(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "F");
                    _s
                });
            ::quote::__private::push_ident(&mut _s, "where");
            ::quote::__private::push_ident(&mut _s, "F");
            ::quote::__private::push_colon(&mut _s);
            ::quote::__private::push_lifetime(&mut _s, "\'static");
            ::quote::__private::push_add(&mut _s);
            ::quote::__private::push_ident(&mut _s, "for");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_ident(&mut _s, "FnOnce");
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_and(&mut _s);
                    ::quote::ToTokens::to_tokens(&bound_lt, &mut _s);
                    ::quote::__private::push_ident(&mut _s, "mut");
                    ::quote::__private::push_ident(&mut _s, "Self");
                    ::quote::__private::push_colon2(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "Output");
                    _s
                });
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Brace,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    ::quote::__private::push_ident(&mut _s, "let");
                    ::quote::__private::push_ident(&mut _s, "y");
                    ::quote::__private::push_eq(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "unsafe");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Brace,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_and(&mut _s);
                            ::quote::__private::push_ident(&mut _s, "mut");
                            ::quote::__private::push_star(&mut _s);
                            ::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_ident(&mut _s, "as");
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "mut");
                                    ::quote::__private::push_ident(&mut _s, "Self");
                                    ::quote::__private::push_ident(&mut _s, "as");
                                    ::quote::__private::push_star(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "mut");
                                    ::quote::__private::push_ident(&mut _s, "Self");
                                    ::quote::__private::push_colon2(&mut _s);
                                    ::quote::__private::push_ident(&mut _s, "Output");
                                    _s
                                });
                            _s
                        });
                    ::quote::__private::push_semi(&mut _s);
                    ::quote::__private::push_ident(&mut _s, "f");
                    ::quote::__private::push_group(&mut _s,
                        ::quote::__private::Delimiter::Parenthesis,
                        {
                            let mut _s = ::quote::__private::TokenStream::new();
                            ::quote::__private::push_ident(&mut _s, "y");
                            _s
                        });
                    _s
                });
            _s
        });
    _s
}quote! {
482        // SAFETY: we assert covariance in `borrowed_checks`
483        unsafe impl<#yoke_lt, #(#tybounds),*> yoke::Yokeable<#yoke_lt>
484        for #name<'static, #(#typarams),*>
485        where
486            #(#static_bounds,)*
487            #(#wherebounds,)*
488            #(#manual_proof_bounds,)*
489            // Adding `Self: Sized` here doesn't work.
490            // `for<#bound_lt> #name<#bound_lt, #(#typarams),*>: Sized`
491            // might work, though. Since these trait bounds are very finicky, it's best to just
492            // not try unless necessary.
493        {
494            type Output = #name<#yoke_lt, #(#typarams),*>;
495            #[inline]
496            fn transform(&#yoke_lt self) -> &#yoke_lt Self::Output {
497                // These are just type asserts, we don't need to run them
498                if false {
499                    // This could, hypothetically, conflict with the name of one of the `FieldTy`s
500                    // we read (and cause a compilation error). However, such a conflict cannot
501                    // cause unsoundness, since this function is in scope no matter what.
502                    // (The problem is that attempting to refer to a type named
503                    // `__yoke_derive_require_yokeable` would instead refer to this function item
504                    // and therefore fail.)
505                    #[allow(dead_code)]
506                    fn __yoke_derive_require_yokeable<
507                        #yoke_lt: #yoke_lt,
508                        T: yoke::Yokeable<#yoke_lt>,
509                    >(_t: *const &#yoke_lt T) {}
510
511                    match self {
512                        #yokeable_checks
513                    }
514                }
515                let output = unsafe { ::core::mem::transmute::<&#yoke_lt Self, &#yoke_lt Self::Output>(self) };
516                if false {
517                    // Same deal as above.
518                    #[allow(dead_code)]
519                    fn __yoke_derive_require_static<
520                        #yoke_lt: #yoke_lt,
521                        T: 'static,
522                    >(_t: *const &#yoke_lt T) {}
523
524                    match output {
525                        #output_checks
526                    }
527                }
528                output
529            }
530            #[inline]
531            fn transform_owned(self) -> Self::Output {
532                unsafe { ::core::mem::transmute::<Self, Self::Output>(self) }
533            }
534            #[inline]
535            unsafe fn make(from: Self::Output) -> Self {
536                unsafe { ::core::mem::transmute::<Self::Output, Self>(from) }
537            }
538            #[inline]
539            fn transform_mut<F>(&#yoke_lt mut self, f: F)
540            where
541                F: 'static + for<#bound_lt> FnOnce(&#bound_lt mut Self::Output) {
542                let y = unsafe { &mut *(self as *mut Self as *mut Self::Output) };
543                f(y)
544            }
545        }
546    }
547}