abi_stable_derive/
sabi_trait.rs

1use crate::{
2    impl_interfacetype::private_associated_type,
3    my_visibility::{RelativeVis, VisibilityKind},
4    parse_utils::parse_str_as_ident,
5    workaround::token_stream_to_string,
6    *,
7};
8
9use std::marker::PhantomData;
10
11use proc_macro2::TokenStream as TokenStream2;
12
13use quote::TokenStreamExt;
14
15use syn::ItemTrait;
16
17use as_derive_utils::{
18    gen_params_in::{GenParamsIn, InWhat},
19    to_token_fn::ToTokenFnMut,
20};
21
22mod attribute_parsing;
23mod common_tokens;
24mod impl_delegations;
25mod lifetime_unelider;
26mod method_where_clause;
27mod methods_tokenizer;
28mod replace_self_path;
29mod trait_definition;
30
31#[cfg(test)]
32mod tests;
33
34use self::{
35    attribute_parsing::SabiTraitOptions,
36    common_tokens::{CommonTokens, IsStaticTrait, LifetimeTokens},
37    lifetime_unelider::LifetimeUnelider,
38    method_where_clause::MethodWhereClause,
39    methods_tokenizer::MethodsTokenizer,
40    trait_definition::{TraitDefinition, TraitMethod},
41};
42
43/// Variables passed to all the `*_items` functions here.
44#[allow(dead_code)]
45#[derive(Copy, Clone)]
46struct TokenizerParams<'a> {
47    arenas: &'a Arenas,
48    ctokens: &'a CommonTokens,
49    config: &'a SabiTraitOptions<'a>,
50    trait_def: &'a TraitDefinition<'a>,
51    vis: VisibilityKind<'a>,
52    submod_vis: RelativeVis<'a>,
53    totrait_def: &'a TraitDefinition<'a>,
54    vtable_trait_decl: &'a TraitDefinition<'a>,
55    vtable_trait_impl: &'a TraitDefinition<'a>,
56    trait_ident: &'a syn::Ident,
57    trait_to: &'a syn::Ident,
58    trait_backend: &'a syn::Ident,
59    trait_interface: &'a syn::Ident,
60    make_vtable_ident: &'a syn::Ident,
61    trait_cto_ident: &'a syn::Ident,
62    /// TokenStreams that don't have a `'lt,` if the trait object requires
63    /// `'static` to be constructed.
64    lt_tokens: &'a LifetimeTokens,
65}
66
67/// The implementation of the `#[sabi_trait]` proc-macro attribute.
68pub fn derive_sabi_trait(item: ItemTrait) -> Result<TokenStream2, syn::Error> {
69    let arenas = Arenas::default();
70    let arenas = &arenas;
71    let ctokens = CommonTokens::new();
72    let ctokens = &ctokens;
73
74    let trait_ident = &item.ident;
75
76    let config = &self::attribute_parsing::parse_attrs_for_sabi_trait(&item, arenas, ctokens)?;
77
78    let trait_def = &config.trait_definition;
79    let lt_tokens = &LifetimeTokens::new(trait_def.is_static);
80    let vis = trait_def.vis;
81    let submod_vis = trait_def.submod_vis;
82
83    let totrait_def = &trait_def.replace_self(WhichItem::TraitObjectImpl)?;
84    let vtable_trait_decl = &trait_def.replace_self(WhichItem::VtableDecl)?;
85    let vtable_trait_impl = &trait_def.replace_self(WhichItem::VtableImpl)?;
86
87    let generated_mod = &parse_str_as_ident(&format!("{}_trait", trait_ident));
88    let trait_to = &parse_str_as_ident(&format!("{}_TO", trait_ident));
89    let trait_backend = &parse_str_as_ident(&format!("{}_Backend", trait_ident));
90    let trait_interface = &parse_str_as_ident(&format!("{}_Interface", trait_ident));
91    let make_vtable_ident = &parse_str_as_ident(&format!("{}_MV", trait_ident));
92    let trait_cto_ident = &parse_str_as_ident(&format!("{}_CTO", trait_ident));
93
94    let mut mod_contents = TokenStream2::default();
95
96    let tokenizer_params = TokenizerParams {
97        arenas,
98        ctokens,
99        config,
100        lt_tokens,
101        trait_def,
102        vis,
103        submod_vis,
104        totrait_def,
105        vtable_trait_decl,
106        vtable_trait_impl,
107        trait_ident,
108        trait_to,
109        trait_backend,
110        trait_interface,
111        make_vtable_ident,
112        trait_cto_ident,
113    };
114
115    first_items(tokenizer_params, &mut mod_contents);
116
117    constructor_items(tokenizer_params, &mut mod_contents);
118
119    trait_and_impl(tokenizer_params, &mut mod_contents);
120
121    methods_impls(tokenizer_params, &mut mod_contents)?;
122
123    declare_vtable(tokenizer_params, &mut mod_contents);
124
125    vtable_impl(tokenizer_params, &mut mod_contents);
126
127    impl_delegations::delegated_impls(tokenizer_params, &mut mod_contents);
128
129    let doc_hidden_attr = config.doc_hidden_attr;
130
131    let mod_docs = if doc_hidden_attr.is_none() {
132        Some(format!(
133            "This module is generated by the \
134             [`#[sabi_trait]`](macro@::abi_stable::sabi_trait) \
135             attribute on \
136            [{trait_}](trait@{trait_})",
137            trait_ = trait_ident,
138        ))
139    } else {
140        None
141    }
142    .into_iter();
143
144    let mut tokens = quote!(
145        #doc_hidden_attr
146        #[doc(inline)]
147        #vis use self::#generated_mod::{
148            #trait_to,
149            #trait_ident,
150            #trait_cto_ident,
151        };
152
153        #doc_hidden_attr
154        #(#[doc = #mod_docs])*
155        #[allow(explicit_outlives_requirements)]
156        #vis mod #generated_mod{
157            #mod_contents
158        }
159    );
160
161    if config.debug_output_tokens {
162        let tokens_str = tokens.to_string();
163        tokens.append_all(quote!(
164            pub const TOKENS: &'static str = #tokens_str;
165        ));
166    }
167
168    // drop(_measure_time1);
169    if config.debug_print_trait {
170        panic!("\n\n\n{}\n\n\n", token_stream_to_string(tokens.clone()));
171    }
172
173    Ok(tokens)
174}
175
176/// Outputs these items:
177///
178/// - `Trait_Backend`:
179///     A type alias to the underlying implementation of the trait object,
180///     which is either RObject
181///
182/// - `Trait_Interface`
183///     A marker type describing the traits that are required when constructing
184///     the underlying implementation of the trait object,
185///     and are then implemented by it,
186///     by implementing `InterfaceType`.
187///
188/// - `Trait_TO`:
189///     The ffi-safe trait object for the trait.
190///
191fn first_items(
192    TokenizerParams {
193        config,
194        ctokens,
195        lt_tokens,
196        trait_def,
197        submod_vis,
198        trait_to,
199        trait_backend,
200        trait_interface,
201        trait_cto_ident,
202        ..
203    }: TokenizerParams,
204    mod_: &mut TokenStream2,
205) {
206    let trait_ident = trait_def.name;
207
208    let doc_hidden_attr = config.doc_hidden_attr;
209
210    let mut uto_params = trait_def.generics_tokenizer(
211        InWhat::ItemDecl,
212        WithAssocTys::Yes(WhichSelf::NoSelf),
213        &lt_tokens.lt_erasedptr,
214    );
215    uto_params.set_no_bounds();
216
217    let mut gen_params_header_rref = trait_def.generics_tokenizer(
218        InWhat::ImplHeader,
219        WithAssocTys::Yes(WhichSelf::NoSelf),
220        &lt_tokens.lt_sub_lt,
221    );
222    gen_params_header_rref.set_no_bounds();
223
224    let gen_params_use_to_rref = trait_def.generics_tokenizer(
225        InWhat::ItemUse,
226        WithAssocTys::Yes(WhichSelf::NoSelf),
227        &lt_tokens.lt_rref,
228    );
229
230    let uto_params_use = trait_def.generics_tokenizer(
231        InWhat::ItemUse,
232        WithAssocTys::Yes(WhichSelf::NoSelf),
233        &lt_tokens.lt_erasedptr,
234    );
235
236    let mut trait_interface_header = trait_def.generics_tokenizer(
237        InWhat::ImplHeader,
238        WithAssocTys::Yes(WhichSelf::NoSelf),
239        &ctokens.ts_empty,
240    );
241    trait_interface_header.set_no_bounds();
242
243    let mut trait_interface_decl = trait_def.generics_tokenizer(
244        InWhat::ItemDecl,
245        WithAssocTys::Yes(WhichSelf::NoSelf),
246        &ctokens.ts_empty,
247    );
248    trait_interface_decl.set_no_bounds();
249    // trait_interface_decl.set_unsized_types();
250
251    let trait_interface_use = trait_def.generics_tokenizer(
252        InWhat::ItemUse,
253        WithAssocTys::Yes(WhichSelf::NoSelf),
254        &ctokens.ts_empty,
255    );
256
257    let to_params = trait_def.generics_tokenizer(
258        InWhat::ItemDecl,
259        WithAssocTys::Yes(WhichSelf::NoSelf),
260        &lt_tokens.lt_erasedptr,
261    );
262
263    let where_preds = (&trait_def.where_preds).into_iter();
264
265    let vtable_args = trait_def.generics_tokenizer(
266        InWhat::ItemUse,
267        WithAssocTys::Yes(WhichSelf::NoSelf),
268        &ctokens.ts_unit_erasedptr,
269    );
270
271    let impld_traits = trait_def.impld_traits.iter().map(|x| &x.ident);
272    let impld_traits_a = impld_traits.clone();
273    let impld_traits_b = impld_traits.clone();
274
275    let unimpld_traits_a = trait_def.unimpld_traits.iter().cloned();
276    let unimpld_traits_b = trait_def.unimpld_traits.iter().cloned();
277
278    let priv_assocty = private_associated_type();
279
280    let object = match trait_def.which_object {
281        WhichObject::DynTrait => quote!(DynTrait),
282        WhichObject::RObject => quote!(RObject),
283    };
284    let vtable_argument = match trait_def.which_object {
285        WhichObject::DynTrait => quote!(__sabi_re::PrefixRef<VTable_Prefix<#vtable_args>>),
286        WhichObject::RObject => quote!(VTable_Prefix<#vtable_args>),
287    };
288
289    let dummy_struct_generics = trait_def.generics_tokenizer(
290        InWhat::DummyStruct,
291        WithAssocTys::Yes(WhichSelf::NoSelf),
292        &ctokens.ts_empty,
293    );
294    // dummy_struct_generics.set_unsized_types();
295
296    let used_trait_object = quote!(#trait_backend<#uto_params_use>);
297
298    let trait_flags = &trait_def.trait_flags;
299    let send_syncness = match (trait_flags.sync, trait_flags.send) {
300        (false, false) => "UnsyncUnsend",
301        (false, true) => "UnsyncSend",
302        (true, false) => "SyncUnsend",
303        (true, true) => "SyncSend",
304    }
305    .piped(parse_str_as_ident);
306
307    let mut trait_backend_docs = String::new();
308
309    let mut trait_interface_docs = String::new();
310
311    let mut trait_to_docs = String::new();
312
313    let mut trait_cto_docs = String::new();
314    if doc_hidden_attr.is_none() {
315        trait_backend_docs = format!(
316            "An alias for the underlying implementation of \
317             [`{trait_to}`](struct@{trait_to}).\
318            ",
319            trait_to = trait_to
320        );
321        trait_interface_docs = format!(
322            "A marker type describing the traits that are required when constructing \
323             [`{trait_to}`](struct@{trait_to}),\
324             and are then implemented by it,
325             by implementing the 
326             [`InterfaceType`](::abi_stable::InterfaceType)
327             trait.",
328            trait_to = trait_to
329        );
330        trait_to_docs = format!(
331            "\
332            The trait object for [{Trait}](trait@{Trait}).\n\
333            \n\
334            There are extra methods on the `obj` field.\n
335            ",
336            Trait = trait_ident
337        );
338        trait_cto_docs = format!(
339            "A type alias for the const-constructible \
340             [`{trait_to}`](struct@{trait_to}).",
341            trait_to = trait_to
342        );
343    }
344    let one_lt = &lt_tokens.one_lt;
345
346    quote!(
347        use super::*;
348
349        use abi_stable::sabi_trait::reexports::{*,__sabi_re};
350
351        use self::#trait_ident as __Trait;
352
353        #[doc=#trait_backend_docs]
354        #submod_vis type #trait_backend<#uto_params>=
355            __sabi_re::#object<
356                #one_lt
357                _ErasedPtr,
358                #trait_interface<#trait_interface_use>,
359                #vtable_argument
360            >;
361
362        #[doc=#trait_cto_docs]
363        #submod_vis type #trait_cto_ident<#gen_params_header_rref>=
364            #trait_to<#gen_params_use_to_rref>;
365
366
367
368        #[doc=#trait_interface_docs]
369        #[repr(C)]
370        #[derive(::abi_stable::StableAbi)]
371        #submod_vis struct #trait_interface<#trait_interface_decl>(
372            __sabi_re::NonOwningPhantom<(#dummy_struct_generics)>
373        );
374
375        impl<#trait_interface_header> #trait_interface<#trait_interface_use> {
376            /// Constructs this type
377            #submod_vis const NEW:Self=#trait_interface(__sabi_re::NonOwningPhantom::NEW);
378        }
379
380
381        #[doc=#trait_to_docs]
382        #[repr(transparent)]
383        #[derive(::abi_stable::StableAbi)]
384        #[sabi(bound(#used_trait_object: ::abi_stable::StableAbi))]
385        #submod_vis struct #trait_to<#to_params>
386        where
387            _ErasedPtr:__GetPointerKind,
388            #(#where_preds)*
389        {
390            ///
391            #submod_vis obj:#used_trait_object,
392            _marker:__sabi_re::UnsafeIgnoredType< __sabi_re::#send_syncness >,
393        }
394
395        const __inside_generated_mod:()={
396            use abi_stable::{
397                InterfaceType,
398                type_level::{
399                    impl_enum::{Implemented,Unimplemented},
400                    trait_marker,
401                },
402            };
403
404            impl<#trait_interface_header>
405                abi_stable::InterfaceType
406                for #trait_interface<#trait_interface_use>
407            {
408                #( type #impld_traits_a=Implemented<trait_marker::#impld_traits_b>; )*
409                #( type #unimpld_traits_a=Unimplemented<trait_marker::#unimpld_traits_b>; )*
410                type #priv_assocty=();
411            }
412        };
413
414    )
415    .to_tokens(mod_);
416}
417
418/// Outputs the trait object constructors.
419fn constructor_items(params: TokenizerParams<'_>, mod_: &mut TokenStream2) {
420    let TokenizerParams {
421        ctokens,
422        totrait_def,
423        submod_vis,
424        trait_ident,
425        trait_to,
426        trait_backend,
427        trait_interface,
428        lt_tokens,
429        make_vtable_ident,
430        ..
431    } = params;
432
433    let doc_hidden_attr = params.config.doc_hidden_attr;
434
435    let trait_params =
436        totrait_def.generics_tokenizer(InWhat::ItemUse, WithAssocTys::No, &ctokens.empty_ts);
437
438    let assoc_tys_a = totrait_def.assoc_tys.keys();
439    let assoc_tys_b = assoc_tys_a.clone();
440    let assoc_tys_c = assoc_tys_a.clone();
441    let assoc_tys_d = assoc_tys_a.clone();
442    let assoc_tys_e = assoc_tys_a.clone();
443    let assoc_tys_f = assoc_tys_a.clone();
444
445    let mut make_vtable_args = totrait_def.generics_tokenizer(
446        InWhat::ItemUse,
447        WithAssocTys::No,
448        &ctokens.ts_make_vtable_args,
449    );
450    make_vtable_args.skip_lifetimes();
451
452    let mut make_vtable_args_const = totrait_def.generics_tokenizer(
453        InWhat::ItemUse,
454        WithAssocTys::No,
455        &ctokens.ts_make_vtable_args_const,
456    );
457    make_vtable_args_const.skip_lifetimes();
458
459    let fn_can_it_downcast_arg = match totrait_def.which_object {
460        WhichObject::DynTrait => quote!(Downcasting),
461        WhichObject::RObject => quote!(),
462    };
463
464    let trait_interface_use = totrait_def.generics_tokenizer(
465        InWhat::ItemUse,
466        WithAssocTys::Yes(WhichSelf::NoSelf),
467        &ctokens.ts_empty,
468    );
469
470    let one_lt = &lt_tokens.one_lt;
471
472    let extra_constraints_ptr = match totrait_def.which_object {
473        WhichObject::DynTrait => quote!(
474            #trait_interface<#trait_interface_use>:
475                ::abi_stable::erased_types::InterfaceType,
476            __sabi_re::DynTraitVTable_Ref<
477                #one_lt
478                _OrigPtr::TransmutedPtr,
479                #trait_interface<#trait_interface_use>,
480            >:
481                __sabi_re::MakeDynTraitVTable<
482                    #one_lt
483                    _OrigPtr::PtrTarget,
484                    _OrigPtr,
485                    Downcasting
486                >,
487        ),
488        WhichObject::RObject => quote!(),
489    };
490
491    let extra_constraints_value = match totrait_def.which_object {
492        WhichObject::DynTrait => quote!(
493            #trait_interface<#trait_interface_use>:
494                ::abi_stable::erased_types::InterfaceType,
495            __sabi_re::DynTraitVTable_Ref<
496                #one_lt
497                __sabi_re::RBox<()>,
498                #trait_interface<#trait_interface_use>,
499            >:
500                __sabi_re::MakeDynTraitVTable<
501                    #one_lt
502                    _Self,
503                    __sabi_re::RBox<_Self>,
504                    Downcasting
505                >,
506        ),
507        WhichObject::RObject => quote!(),
508    };
509
510    let extra_constraints_const = match totrait_def.which_object {
511        WhichObject::DynTrait => quote!(
512            #trait_interface<#trait_interface_use>:
513                ::abi_stable::erased_types::InterfaceType,
514            __sabi_re::DynTraitVTable_Ref<
515                #one_lt
516                __sabi_re::RRef<'_sub, ()>,
517                #trait_interface<#trait_interface_use>,
518            >:
519                __sabi_re::MakeDynTraitVTable<
520                    #one_lt
521                    _Self,
522                    &'_sub _Self,
523                    Downcasting
524                >,
525        ),
526        WhichObject::RObject => quote!(),
527    };
528
529    let gen_params_header = totrait_def.generics_tokenizer(
530        InWhat::ImplHeader,
531        WithAssocTys::Yes(WhichSelf::NoSelf),
532        &lt_tokens.lt_erasedptr,
533    );
534
535    let gen_params_use_to = totrait_def.generics_tokenizer(
536        InWhat::ItemUse,
537        WithAssocTys::Yes(WhichSelf::NoSelf),
538        &lt_tokens.lt_erasedptr,
539    );
540
541    let gen_params_header_rbox = totrait_def.generics_tokenizer(
542        InWhat::ImplHeader,
543        WithAssocTys::Yes(WhichSelf::NoSelf),
544        &lt_tokens.lt,
545    );
546
547    let gen_params_use_to_rbox = totrait_def.generics_tokenizer(
548        InWhat::ItemUse,
549        WithAssocTys::Yes(WhichSelf::NoSelf),
550        &lt_tokens.lt_rbox,
551    );
552
553    let uto_params_use = totrait_def.generics_tokenizer(
554        InWhat::ItemUse,
555        WithAssocTys::Yes(WhichSelf::NoSelf),
556        &lt_tokens.lt_erasedptr,
557    );
558
559    let trait_interface_use = totrait_def.generics_tokenizer(
560        InWhat::ItemUse,
561        WithAssocTys::Yes(WhichSelf::NoSelf),
562        &ctokens.ts_empty,
563    );
564
565    let gen_params_header_rref = totrait_def.generics_tokenizer(
566        InWhat::ImplHeader,
567        WithAssocTys::Yes(WhichSelf::NoSelf),
568        &lt_tokens.lt_sub_lt,
569    );
570
571    let gen_params_use_to_rref = totrait_def.generics_tokenizer(
572        InWhat::ItemUse,
573        WithAssocTys::Yes(WhichSelf::NoSelf),
574        &lt_tokens.lt_rref,
575    );
576
577    let mut shared_docs = String::new();
578    let mut from_ptr_docs = String::new();
579    let mut from_value_docs = String::new();
580    let mut from_const_docs = String::new();
581
582    if doc_hidden_attr.is_none() {
583        shared_docs = "\
584            <br><br>\
585            `can_it_downcast` describes whether the trait object can be \
586            converted back into the original type or not.<br>\n\
587            Its possible values are `TD_CanDowncast` and `TD_Opaque`.\n\
588        "
589        .to_string();
590
591        from_ptr_docs = format!(
592            "Constructs this trait object from a pointer to a type that implements `{trait_}`.\n\
593             \n\
594             This method is automatically generated,\n\
595             for more documentation you can look at\n\
596             [`abi_stable::docs::sabi_trait_inherent#from_ptr-method`]\n\
597            ",
598            trait_ = trait_ident
599        );
600
601        from_value_docs = format!(
602            "Constructs this trait from a type that implements `{trait_}`.\n\
603             \n\
604             This method is automatically generated,\n\
605             for more documentation you can look at\n\
606             [`abi_stable::docs::sabi_trait_inherent#from_value-method`]\n\
607            ",
608            trait_ = trait_ident
609        );
610
611        from_const_docs = format!(
612            "Constructs this trait from a constant of a type that implements `{trait_}`.\n\
613             \n\
614             This method is automatically generated,\n\
615             for more documentation you can look at\n\
616             [`abi_stable::docs::sabi_trait_inherent#from_const-method`]\n\
617              \n\
618             You can construct the `vtable_for` parameter with \
619             [`{make_vtable_ident}::VTABLE`].\n\
620            ",
621            trait_ = trait_ident,
622            make_vtable_ident = make_vtable_ident,
623        );
624    }
625
626    let reborrow_methods = reborrow_methods_tokenizer(params);
627
628    let plus_lt = &lt_tokens.plus_lt;
629
630    let constructing_backend = match totrait_def.which_object {
631        WhichObject::DynTrait => quote!(
632            #trait_backend::from_const(
633                ptr,
634                can_it_downcast,
635                #make_vtable_ident::<#make_vtable_args_const>::VTABLE_INNER
636            )
637        ),
638        WhichObject::RObject => quote!({
639            let _ = __sabi_re::ManuallyDrop::new(can_it_downcast);
640            #trait_backend::with_vtable_const::<_, Downcasting>(
641                ptr,
642                #make_vtable_ident::<#make_vtable_args_const>::VTABLE_INNER
643            )
644        }),
645    };
646
647    quote!(
648        impl<#gen_params_header> #trait_to<#gen_params_use_to>
649        where
650            _ErasedPtr: __sabi_re::AsPtr<PtrTarget = ()>,
651        {
652            #[doc=#from_ptr_docs]
653            #[doc=#shared_docs]
654            #submod_vis fn from_ptr<_OrigPtr,Downcasting>(
655                ptr:_OrigPtr,
656                can_it_downcast:Downcasting,
657            )->Self
658            where
659                _OrigPtr:
660                    __sabi_re::CanTransmuteElement<(),TransmutedPtr=_ErasedPtr>,
661                _OrigPtr::PtrTarget:
662                    #trait_ident<#trait_params #( #assoc_tys_a= #assoc_tys_b, )* >+
663                    Sized
664                    #plus_lt,
665                #trait_interface<#trait_interface_use>:
666                    __sabi_re::GetRObjectVTable<
667                        Downcasting,_OrigPtr::PtrTarget,_ErasedPtr,_OrigPtr
668                    >,
669                #extra_constraints_ptr
670            {
671                let _can_it_downcast=can_it_downcast;
672                unsafe{
673                    Self{
674                        obj:#trait_backend::with_vtable::<_,#fn_can_it_downcast_arg>(
675                            ptr,
676                            #make_vtable_ident::<#make_vtable_args>::VTABLE_INNER
677                        ),
678                        _marker:__sabi_re::UnsafeIgnoredType::DEFAULT,
679                    }
680                }
681            }
682
683            /// Constructs this trait object from its underlying implementation.
684            ///
685            /// This method is automatically generated,
686            /// for more documentation you can look at
687            /// [`abi_stable::docs::sabi_trait_inherent#from_sabi-method`]
688            #submod_vis fn from_sabi(obj:#trait_backend<#uto_params_use>)->Self{
689                Self{
690                    obj,
691                    _marker:__sabi_re::UnsafeIgnoredType::DEFAULT,
692                }
693            }
694
695            #reborrow_methods
696        }
697
698        impl<#gen_params_header_rbox> #trait_to<#gen_params_use_to_rbox> {
699            #[doc=#from_value_docs]
700            #[doc=#shared_docs]
701            #submod_vis fn from_value<_Self,Downcasting>(
702                ptr:_Self,
703                can_it_downcast:Downcasting,
704            )->Self
705            where
706                _Self:
707                    #trait_ident<#trait_params #( #assoc_tys_c= #assoc_tys_d, )* >
708                    #plus_lt,
709                #trait_interface<#trait_interface_use>:
710                    __sabi_re::GetRObjectVTable<
711                        Downcasting,_Self,__sabi_re::RBox<()>,__sabi_re::RBox<_Self>
712                    >,
713                #extra_constraints_value
714            {
715                Self::from_ptr::<
716                    __sabi_re::RBox<_Self>,
717                    Downcasting
718                >(__sabi_re::RBox::new(ptr),can_it_downcast)
719            }
720        }
721
722        impl<#gen_params_header_rref> #trait_to<#gen_params_use_to_rref>{
723            #[doc=#from_const_docs]
724            #[doc=#shared_docs]
725            #submod_vis const fn from_const<_Self,Downcasting>(
726                ptr:&'_sub _Self,
727                can_it_downcast:Downcasting,
728            )->Self
729            where
730                _Self:
731                    #trait_ident<#trait_params #( #assoc_tys_e = #assoc_tys_f, )* >
732                    #plus_lt,
733                _Self: #one_lt
734                #trait_interface<#trait_interface_use>:
735                    __sabi_re::GetRObjectVTable<
736                        Downcasting, _Self, __sabi_re::RRef<'_sub, ()>, &'_sub _Self
737                    >,
738                #extra_constraints_const
739            {
740                unsafe{
741                    Self{
742                        obj:#constructing_backend,
743                        _marker:__sabi_re::UnsafeIgnoredType::DEFAULT,
744                    }
745                }
746            }
747        }
748
749    )
750    .to_tokens(mod_);
751}
752
753/// Returns a tokenizer for the reborrowing methods
754fn reborrow_methods_tokenizer(
755    TokenizerParams {
756        totrait_def,
757        submod_vis,
758        trait_to,
759        lt_tokens,
760        ..
761    }: TokenizerParams<'_>,
762) -> impl ToTokens + '_ {
763    ToTokenFnMut::new(move |ts| {
764        let traits = totrait_def.trait_flags;
765        // If the trait object doesn't have both Sync+Send as supertraits or neither,
766        // it can't be reborrowed.
767        if traits.sync != traits.send {
768            return;
769        }
770
771        let gen_params_use_ref = totrait_def.generics_tokenizer(
772            InWhat::ItemUse,
773            WithAssocTys::Yes(WhichSelf::NoSelf),
774            &lt_tokens.lt_rref,
775        );
776
777        let gen_params_use_mut = totrait_def.generics_tokenizer(
778            InWhat::ItemUse,
779            WithAssocTys::Yes(WhichSelf::NoSelf),
780            &lt_tokens.lt_rmut,
781        );
782
783        quote!(
784            /// Reborrows this trait object to a reference-based trait object.
785            ///
786            /// This method is automatically generated,
787            /// for more documentation you can look at
788            /// [`abi_stable::docs::sabi_trait_inherent#sabi_reborrow-method`]
789            #submod_vis fn sabi_reborrow<'_sub>(&'_sub self)->#trait_to<#gen_params_use_ref> {
790                let x = self.obj.reborrow();
791                // This is transmuting the pointer type parameter of the vtable.
792                let x = unsafe{ __sabi_re::transmute(x) };
793                #trait_to::from_sabi(x)
794            }
795
796            /// Reborrows this trait object to a mutable-reference-based trait object.
797            ///
798            /// This method is automatically generated,
799            /// for more documentation you can look at
800            /// [`abi_stable::docs::sabi_trait_inherent#sabi_reborrow_mut-method`]
801            #submod_vis fn sabi_reborrow_mut<'_sub>(&'_sub mut self)->#trait_to<#gen_params_use_mut>
802            where
803                _ErasedPtr: __sabi_re::AsMutPtr<PtrTarget=()>
804            {
805                let x = self.obj.reborrow_mut();
806                // This is transmuting the pointer type parameter of the vtable.
807                let x = unsafe{ __sabi_re::transmute(x) };
808                #trait_to::from_sabi(x)
809            }
810        )
811        .to_tokens(ts);
812    })
813}
814
815/// Outputs the annotated trait (as modified by the proc-macro)
816/// and an implementation of the trait for the generated trait object.
817fn trait_and_impl(
818    TokenizerParams {
819        ctokens,
820        submod_vis,
821        trait_def,
822        trait_to,
823        lt_tokens,
824        trait_ident,
825        ..
826    }: TokenizerParams,
827    mod_: &mut TokenStream2,
828) {
829    let other_attrs = trait_def.other_attrs;
830    let gen_params_trait =
831        trait_def.generics_tokenizer(InWhat::ItemDecl, WithAssocTys::No, &ctokens.empty_ts);
832    let where_preds = (&trait_def.where_preds).into_iter();
833    let where_preds_b = where_preds.clone();
834    let methods_tokenizer_def = trait_def.methods_tokenizer(WhichItem::Trait);
835    let methods_tokenizer_impl = trait_def.methods_tokenizer(WhichItem::TraitImpl);
836    let lifetime_bounds_a = trait_def.lifetime_bounds.iter();
837    let lifetime_bounds_c = trait_def.lifetime_bounds.iter();
838    let super_traits_a = trait_def.impld_traits.iter().map(|t| &t.bound);
839    let super_traits_b = super_traits_a.clone();
840
841    let assoc_tys_a = trait_def.assoc_tys.values().map(|x| &x.assoc_ty);
842
843    let unsafety = trait_def.item.unsafety;
844
845    let erased_ptr_bounds = trait_def.erased_ptr_preds();
846
847    quote!(
848        #[allow(clippy::needless_lifetimes, clippy::new_ret_no_self)]
849        #( #other_attrs )*
850        #submod_vis #unsafety trait #trait_ident<
851            #gen_params_trait
852        >: #( #super_traits_a + )* #( #lifetime_bounds_a + )*
853        where
854            #(#where_preds,)*
855        {
856            #( #assoc_tys_a )*
857
858            #methods_tokenizer_def
859        }
860    )
861    .to_tokens(mod_);
862
863    let gen_params_use_trait =
864        trait_def.generics_tokenizer(InWhat::ItemUse, WithAssocTys::No, &ctokens.empty_ts);
865
866    if !trait_def.disable_trait_impl {
867        let gen_params_header = trait_def.generics_tokenizer(
868            InWhat::ImplHeader,
869            WithAssocTys::Yes(WhichSelf::NoSelf),
870            &lt_tokens.lt_erasedptr,
871        );
872        let gen_params_use_to = trait_def.generics_tokenizer(
873            InWhat::ItemUse,
874            WithAssocTys::Yes(WhichSelf::NoSelf),
875            &lt_tokens.lt_erasedptr,
876        );
877
878        let assoc_ty_named_a = trait_def.assoc_tys.values().map(|x| &x.assoc_ty.ident);
879        let assoc_ty_named_b = assoc_ty_named_a.clone();
880
881        quote!(
882            #[deny(unsafe_op_in_unsafe_fn)]
883            #[allow(
884                clippy::needless_lifetimes,
885                clippy::new_ret_no_self,
886            )]
887            impl<#gen_params_header> #trait_ident<#gen_params_use_trait>
888            for #trait_to<#gen_params_use_to>
889            where
890                Self:#( #super_traits_b + )* #(#lifetime_bounds_c+)*  ,
891                #erased_ptr_bounds
892                #(#where_preds_b,)*
893            {
894                #( type #assoc_ty_named_a=#assoc_ty_named_b; )*
895
896                #methods_tokenizer_impl
897            }
898        )
899        .to_tokens(mod_);
900    }
901}
902
903/// An inherent implementation of the generated trait object,
904/// which mirrors the trait definition.
905fn methods_impls(param: TokenizerParams, mod_: &mut TokenStream2) -> Result<(), syn::Error> {
906    let TokenizerParams {
907        totrait_def,
908        trait_to,
909        ctokens,
910        lt_tokens,
911        ..
912    } = param;
913
914    let impl_where_preds = totrait_def.trait_impl_where_preds()?;
915
916    let super_traits_a = totrait_def.impld_traits.iter().map(|t| &t.bound);
917
918    let gen_params_header = totrait_def.generics_tokenizer(
919        InWhat::ImplHeader,
920        WithAssocTys::Yes(WhichSelf::NoSelf),
921        &lt_tokens.lt_erasedptr,
922    );
923    let gen_params_use_to = totrait_def.generics_tokenizer(
924        InWhat::ItemUse,
925        WithAssocTys::Yes(WhichSelf::NoSelf),
926        &lt_tokens.lt_erasedptr,
927    );
928
929    let generics_use1 = totrait_def.generics_tokenizer(
930        InWhat::ItemUse,
931        WithAssocTys::Yes(WhichSelf::NoSelf),
932        &ctokens.ts_unit_erasedptr,
933    );
934
935    let methods_tokenizer_def = totrait_def.methods_tokenizer(WhichItem::TraitObjectImpl);
936
937    quote!(
938        #[allow(clippy::needless_lifetimes, clippy::new_ret_no_self)]
939        impl<#gen_params_header> #trait_to<#gen_params_use_to>
940        where
941            _ErasedPtr: __sabi_re::AsPtr<PtrTarget = ()>,
942            Self:#( #super_traits_a + )*  ,
943            #impl_where_preds
944        {
945            #[inline]
946            fn sabi_vtable(
947                &self
948            )-> VTable_Ref<#generics_use1> {
949                unsafe{
950                    VTable_Ref(self.obj.sabi_et_vtable())
951                }
952            }
953
954            #methods_tokenizer_def
955        }
956    )
957    .to_tokens(mod_);
958
959    Ok(())
960}
961
962/// Outputs the vtable struct.
963fn declare_vtable(
964    TokenizerParams {
965        ctokens,
966        vtable_trait_decl,
967        submod_vis,
968        trait_interface,
969        ..
970    }: TokenizerParams,
971    mod_: &mut TokenStream2,
972) {
973    let generics_decl = vtable_trait_decl.generics_tokenizer(
974        InWhat::ItemDecl,
975        WithAssocTys::Yes(WhichSelf::NoSelf),
976        &ctokens.ts_self_erasedptr,
977    );
978
979    let mut generics_decl_unbounded = generics_decl;
980    generics_decl_unbounded.set_no_bounds();
981
982    let mut generics_use0 = vtable_trait_decl.generics_tokenizer(
983        InWhat::DummyStruct,
984        WithAssocTys::Yes(WhichSelf::NoSelf),
985        &ctokens.ts_self_erasedptr,
986    );
987    generics_use0.set_no_bounds();
988
989    let derive_attrs = vtable_trait_decl.derive_attrs;
990
991    let methods_tokenizer = vtable_trait_decl.methods_tokenizer(WhichItem::VtableDecl);
992
993    let lifetime_bounds = if vtable_trait_decl.lifetime_bounds.is_empty() {
994        None
995    } else {
996        let mut lifetime_bounds = quote!(_Self:);
997        for lt in &vtable_trait_decl.lifetime_bounds {
998            lifetime_bounds.append_all(quote!(#lt +));
999        }
1000        lifetime_bounds.append(parse_str_as_ident("Sized"));
1001        Some(lifetime_bounds)
1002    }
1003    .into_iter();
1004
1005    let trait_interface_use = vtable_trait_decl.generics_tokenizer(
1006        InWhat::ItemUse,
1007        WithAssocTys::Yes(WhichSelf::NoSelf),
1008        &ctokens.ts_empty,
1009    );
1010
1011    let robject_vtable = quote!(
1012        __sabi_re::RObjectVtable_Ref<
1013            _Self,
1014            _ErasedPtr,
1015            #trait_interface<#trait_interface_use>
1016        >
1017    );
1018
1019    quote!(
1020
1021        #[repr(C)]
1022        #[derive(abi_stable::StableAbi)]
1023        #[sabi(kind(Prefix(prefix_ref = VTable_Ref)))]
1024        #[sabi(missing_field(panic))]
1025        #( #[sabi(prefix_bound(#lifetime_bounds))] )*
1026        #[sabi(bound(#robject_vtable: ::abi_stable::StableAbi))]
1027        #(#derive_attrs)*
1028        #[doc(hidden)]
1029        #submod_vis struct VTable<#generics_decl>
1030        where
1031            _ErasedPtr:__GetPointerKind,
1032        {
1033            _sabi_tys: __sabi_re::NonOwningPhantom<(#generics_use0)>,
1034
1035            _sabi_vtable:#robject_vtable,
1036
1037            #methods_tokenizer
1038        }
1039    )
1040    .to_tokens(mod_);
1041}
1042
1043/// Outputs the vtable impl block with both:
1044///
1045/// - A constant where the vtable is constructed.
1046///
1047/// - The methods that the vtable is constructed with.
1048///
1049fn vtable_impl(
1050    TokenizerParams {
1051        ctokens,
1052        vtable_trait_impl,
1053        trait_interface,
1054        trait_ident,
1055        make_vtable_ident,
1056        lt_tokens,
1057        ..
1058    }: TokenizerParams,
1059    mod_: &mut TokenStream2,
1060) {
1061    let struct_decl_generics = vtable_trait_impl.generics_tokenizer(
1062        InWhat::ItemDecl,
1063        WithAssocTys::No,
1064        &ctokens.ts_getvtable_params,
1065    );
1066
1067    let dummy_struct_tys = vtable_trait_impl.generics_tokenizer(
1068        InWhat::DummyStruct,
1069        WithAssocTys::No,
1070        &ctokens.ts_getvtable_dummy_struct_fields,
1071    );
1072
1073    let impl_header_generics = vtable_trait_impl.generics_tokenizer(
1074        InWhat::ImplHeader,
1075        WithAssocTys::No,
1076        &ctokens.ts_getvtable_params,
1077    );
1078
1079    let makevtable_generics = vtable_trait_impl.generics_tokenizer(
1080        InWhat::ItemUse,
1081        WithAssocTys::No,
1082        &ctokens.ts_getvtable_params,
1083    );
1084
1085    let trait_generics =
1086        vtable_trait_impl.generics_tokenizer(InWhat::ItemUse, WithAssocTys::No, &ctokens.empty_ts);
1087
1088    let withmetadata_generics = vtable_trait_impl.generics_tokenizer(
1089        InWhat::ItemUse,
1090        WithAssocTys::Yes(WhichSelf::Underscore),
1091        &ctokens.ts_self_erasedptr,
1092    );
1093
1094    let trait_interface_use = vtable_trait_impl.generics_tokenizer(
1095        InWhat::ItemUse,
1096        WithAssocTys::Yes(WhichSelf::Underscore),
1097        &ctokens.ts_empty,
1098    );
1099
1100    let method_names_a = vtable_trait_impl.methods.iter().map(|m| m.name);
1101    let method_names_b = method_names_a.clone();
1102
1103    let vtable_generics = vtable_trait_impl.generics_tokenizer(
1104        InWhat::ItemUse,
1105        WithAssocTys::Yes(WhichSelf::Underscore),
1106        &ctokens.ts_unit_erasedptr,
1107    );
1108
1109    let methods_tokenizer = vtable_trait_impl.methods_tokenizer(WhichItem::VtableImpl);
1110
1111    let one_lt = &lt_tokens.one_lt;
1112
1113    let extra_constraints = match vtable_trait_impl.which_object {
1114        WhichObject::DynTrait => quote!(
1115            #trait_interface<#trait_interface_use>:
1116                ::abi_stable::erased_types::InterfaceType,
1117
1118            __sabi_re::DynTraitVTable_Ref<
1119                #one_lt
1120                _ErasedPtr,
1121                #trait_interface<#trait_interface_use>,
1122            >:
1123                __sabi_re::MakeDynTraitVTable<
1124                    #one_lt
1125                    _Self,
1126                    _OrigPtr,
1127                    IA,
1128                >,
1129        ),
1130        WhichObject::RObject => quote!(),
1131    };
1132
1133    quote!(
1134        struct #make_vtable_ident<#struct_decl_generics>(#dummy_struct_tys);
1135
1136        #[deny(unsafe_op_in_unsafe_fn)]
1137        impl<#impl_header_generics> #make_vtable_ident<#makevtable_generics>
1138        where
1139            _Self: #trait_ident<#trait_generics>,
1140            _OrigPtr:
1141                __sabi_re::CanTransmuteElement<(), PtrTarget = _Self, TransmutedPtr = _ErasedPtr>,
1142            _ErasedPtr:__sabi_re::AsPtr<PtrTarget=()>,
1143            #trait_interface<#trait_interface_use>:
1144                __sabi_re::GetRObjectVTable<IA,_Self,_ErasedPtr,_OrigPtr>,
1145            #extra_constraints
1146        {
1147            const TMP0: __sabi_re::WithMetadata<
1148                VTable<#withmetadata_generics>
1149            >={
1150                __sabi_re::WithMetadata::new(
1151                    VTable{
1152                        _sabi_tys: __sabi_re::NonOwningPhantom::NEW,
1153                        _sabi_vtable:__sabi_re::GetRObjectVTable::ROBJECT_VTABLE,
1154                        #(
1155                            #method_names_a:Self::#method_names_b,
1156                        )*
1157                    }
1158                )
1159            };
1160
1161            const VTABLE_INNER: __sabi_re::PrefixRef<VTable_Prefix<#vtable_generics> > =unsafe{
1162                __sabi_re::WithMetadata::raw_as_prefix(&Self::TMP0)
1163                    .cast() // erasing the `_Self` parameter
1164            };
1165
1166            #methods_tokenizer
1167        }
1168    )
1169    .to_tokens(mod_);
1170}
1171
1172#[derive(Debug, Clone, PartialEq, Eq)]
1173pub(crate) enum SelfParam<'a> {
1174    ByRef {
1175        lifetime: Option<&'a syn::Lifetime>,
1176        is_mutable: bool,
1177    },
1178    ByVal,
1179}
1180
1181/// Which item this is refering to.
1182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1183pub(crate) enum WhichItem {
1184    /// the method in the trait definition
1185    Trait,
1186    /// the method in the trait implemetation for the generated trait object.
1187    TraitImpl,
1188    /// the methods in the inherent implemetation of the generated trait object.
1189    TraitObjectImpl,
1190    /// the fields of the trait object vtable.
1191    VtableDecl,
1192    /// the methods used to construct the vtable.
1193    VtableImpl,
1194}
1195
1196/// Which type used to implement the trait object.
1197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1198pub(crate) enum WhichObject {
1199    DynTrait,
1200    RObject,
1201}
1202
1203impl Default for WhichObject {
1204    fn default() -> Self {
1205        WhichObject::RObject
1206    }
1207}
1208
1209/// Which Self type to get the associated types from.
1210#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1211pub(crate) enum WhichSelf {
1212    /// Self::AssocTy
1213    #[allow(dead_code)]
1214    Regular,
1215    /// _Self::AssocTy
1216    Underscore,
1217    /// <_OrigPtr as __Trait< <generic_params> >>::AssocTy
1218    #[allow(dead_code)]
1219    FullyQualified,
1220    /// AssocTy
1221    NoSelf,
1222}
1223
1224/// Whether to include associated types when printing generic parameters.
1225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1226pub(crate) enum WithAssocTys {
1227    No,
1228    Yes(WhichSelf),
1229}