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#[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 lt_tokens: &'a LifetimeTokens,
65}
66
67pub 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 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
176fn 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 <_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 <_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 <_tokens.lt_rref,
228 );
229
230 let uto_params_use = trait_def.generics_tokenizer(
231 InWhat::ItemUse,
232 WithAssocTys::Yes(WhichSelf::NoSelf),
233 <_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 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 <_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 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 = <_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 #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 #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
418fn 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 = <_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 <_tokens.lt_erasedptr,
533 );
534
535 let gen_params_use_to = totrait_def.generics_tokenizer(
536 InWhat::ItemUse,
537 WithAssocTys::Yes(WhichSelf::NoSelf),
538 <_tokens.lt_erasedptr,
539 );
540
541 let gen_params_header_rbox = totrait_def.generics_tokenizer(
542 InWhat::ImplHeader,
543 WithAssocTys::Yes(WhichSelf::NoSelf),
544 <_tokens.lt,
545 );
546
547 let gen_params_use_to_rbox = totrait_def.generics_tokenizer(
548 InWhat::ItemUse,
549 WithAssocTys::Yes(WhichSelf::NoSelf),
550 <_tokens.lt_rbox,
551 );
552
553 let uto_params_use = totrait_def.generics_tokenizer(
554 InWhat::ItemUse,
555 WithAssocTys::Yes(WhichSelf::NoSelf),
556 <_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 <_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 <_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 = <_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 #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
753fn 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 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 <_tokens.lt_rref,
775 );
776
777 let gen_params_use_mut = totrait_def.generics_tokenizer(
778 InWhat::ItemUse,
779 WithAssocTys::Yes(WhichSelf::NoSelf),
780 <_tokens.lt_rmut,
781 );
782
783 quote!(
784 #submod_vis fn sabi_reborrow<'_sub>(&'_sub self)->#trait_to<#gen_params_use_ref> {
790 let x = self.obj.reborrow();
791 let x = unsafe{ __sabi_re::transmute(x) };
793 #trait_to::from_sabi(x)
794 }
795
796 #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 let x = unsafe{ __sabi_re::transmute(x) };
808 #trait_to::from_sabi(x)
809 }
810 )
811 .to_tokens(ts);
812 })
813}
814
815fn 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 <_tokens.lt_erasedptr,
871 );
872 let gen_params_use_to = trait_def.generics_tokenizer(
873 InWhat::ItemUse,
874 WithAssocTys::Yes(WhichSelf::NoSelf),
875 <_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
903fn 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 <_tokens.lt_erasedptr,
922 );
923 let gen_params_use_to = totrait_def.generics_tokenizer(
924 InWhat::ItemUse,
925 WithAssocTys::Yes(WhichSelf::NoSelf),
926 <_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
962fn 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
1043fn 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 = <_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() };
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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1183pub(crate) enum WhichItem {
1184 Trait,
1186 TraitImpl,
1188 TraitObjectImpl,
1190 VtableDecl,
1192 VtableImpl,
1194}
1195
1196#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1211pub(crate) enum WhichSelf {
1212 #[allow(dead_code)]
1214 Regular,
1215 Underscore,
1217 #[allow(dead_code)]
1219 FullyQualified,
1220 NoSelf,
1222}
1223
1224#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1226pub(crate) enum WithAssocTys {
1227 No,
1228 Yes(WhichSelf),
1229}