1use super::ext::*;
2use super::generics::ParsedGenerics;
3use crate::util::*;
4use itertools::*;
5use proc_macro2::TokenStream;
6use quote::*;
7use std::collections::{BTreeMap, HashMap};
8use syn::parse::{Parse, ParseStream};
9use syn::punctuated::Punctuated;
10use syn::*;
11
12pub struct AliasPath {
13 path: Path,
14 alias: Option<Ident>,
15}
16
17impl Parse for AliasPath {
18 fn parse(input: ParseStream) -> Result<Self> {
19 let path = input.parse()?;
20
21 let alias = if input.parse::<Token![=]>().is_ok() {
22 Some(input.parse::<Ident>()?)
23 } else {
24 None
25 };
26
27 Ok(Self { path, alias })
28 }
29}
30
31impl AliasPath {
32 fn prelude_remap(self) -> Self {
33 Self {
34 path: prelude_remap(self.path),
35 alias: self.alias,
36 }
37 }
38
39 fn ext_abs_remap(self) -> Self {
40 Self {
41 path: ext_abs_remap(self.path),
42 alias: self.alias,
43 }
44 }
45}
46
47pub struct TraitInfo {
49 path: Path,
50 raw_ident: Ident,
51 name_ident: Ident,
52 generics: ParsedGenerics,
53 assocs: ParsedGenerics,
54 vtbl_name: Ident,
55 ret_tmp_typename: Ident,
56 ret_tmp_name: Ident,
57 enable_vtbl_name: Ident,
58 lc_name: Ident,
59 vtbl_typename: Ident,
60 vtbl_get_ident: Ident,
61 assoc_bind_ident: Ident,
62}
63
64impl PartialEq for TraitInfo {
65 fn eq(&self, o: &Self) -> bool {
66 self.name_ident == o.name_ident
67 }
68}
69
70impl Eq for TraitInfo {}
71
72impl Ord for TraitInfo {
73 fn cmp(&self, o: &Self) -> std::cmp::Ordering {
74 self.name_ident.cmp(&o.name_ident)
75 }
76}
77
78impl PartialOrd for TraitInfo {
79 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
80 Some(self.cmp(other))
81 }
82}
83
84impl From<AliasPath> for TraitInfo {
85 fn from(in_path: AliasPath) -> Self {
86 let (path, raw_ident, mut gens) =
87 split_path_ident(&in_path.path).expect("Failed to split path by idents");
88
89 let mut name_ident = raw_ident.clone();
90
91 let mut lc_ident = raw_ident.to_string().to_lowercase();
92
93 if let Some(alias) = in_path.alias {
94 lc_ident = alias.to_string().to_lowercase();
95 name_ident = alias;
96 }
97
98 let mut assocs_map = BTreeMap::new();
99
100 if let Some(gens) = &mut gens {
101 while let Some(GenericArgument::Binding(_)) = gens.last() {
102 let v = gens.pop().unwrap().into_value();
103 if let GenericArgument::Binding(v) = v {
104 assocs_map.insert(v.ident, v.ty);
105 }
106 }
107 }
108
109 let mut assocs = Punctuated::new();
110
111 for (_, ty) in assocs_map {
112 assocs.push_value(GenericArgument::Type(ty.clone()));
113 assocs.push_punct(Default::default());
114 }
115
116 Self {
117 vtbl_name: format_ident!("vtbl_{}", lc_ident),
118 lc_name: format_ident!("{}", lc_ident),
119 vtbl_typename: format_ident!("{}Vtbl", raw_ident),
120 vtbl_get_ident: format_ident!("{}VtblGet", raw_ident),
121 assoc_bind_ident: format_ident!("{}AssocBind", raw_ident),
122 ret_tmp_typename: format_ident!("{}RetTmp", raw_ident),
123 ret_tmp_name: format_ident!("ret_tmp_{}", lc_ident),
124 enable_vtbl_name: format_ident!("enable_{}", lc_ident),
125 path,
126 raw_ident,
127 name_ident,
128 generics: ParsedGenerics::from(gens.as_ref()),
129 assocs: ParsedGenerics::from(&assocs),
130 }
131 }
132}
133
134#[cfg_attr(feature = "unstable", allow(unused))]
136pub struct TraitGroup {
137 name: Ident,
138 cont_name: Ident,
139 generics: ParsedGenerics,
140 mandatory_vtbl: Vec<TraitInfo>,
141 optional_vtbl: Vec<TraitInfo>,
142 ext_traits: HashMap<Ident, (Path, ItemTrait)>,
143 extra_filler_traits: bool,
144}
145
146impl Parse for TraitGroup {
147 fn parse(input: ParseStream) -> Result<Self> {
148 let name = input.parse()?;
149
150 let generics = input.parse()?;
151
152 parse_brace_content(input).ok();
154
155 input.parse::<Token![,]>()?;
156 let mandatory_traits = parse_maybe_braced::<AliasPath>(input)?;
157
158 input.parse::<Token![,]>()?;
159 let optional_traits = parse_maybe_braced::<AliasPath>(input)?;
160
161 let ext_trait_defs = if input.parse::<Token![,]>().is_ok() {
162 parse_maybe_braced::<ItemTrait>(input)?
163 } else {
164 vec![]
165 };
166
167 let mut ext_traits = HashMap::new();
168
169 let mut mandatory_vtbl: Vec<TraitInfo> = mandatory_traits
170 .into_iter()
171 .map(AliasPath::prelude_remap)
172 .map(TraitInfo::from)
173 .collect();
174 mandatory_vtbl.sort();
175
176 let mut optional_vtbl: Vec<TraitInfo> = optional_traits
177 .into_iter()
178 .map(AliasPath::prelude_remap)
179 .map(TraitInfo::from)
180 .collect();
181 optional_vtbl.sort();
182
183 let store_exports = get_exports();
184 let store_traits = get_store();
185
186 let mut crate_path: Path = parse2(crate_path()).expect("Failed to parse crate path");
187
188 if !crate_path.segments.empty_or_trailing() {
189 crate_path.segments.push_punct(Default::default());
190 }
191
192 for vtbl in mandatory_vtbl.iter_mut().chain(optional_vtbl.iter_mut()) {
196 let is_ext = match (vtbl.path.leading_colon, vtbl.path.segments.first()) {
197 (_, Some(x)) => x.ident == "ext",
198 _ => false,
199 };
200
201 if !is_ext {
202 continue;
203 }
204
205 if let Some(tr) = ext_trait_defs.iter().find(|tr| tr.ident == vtbl.raw_ident) {
207 let leading_colon = std::mem::replace(&mut vtbl.path.leading_colon, None);
209
210 let old_path = std::mem::replace(
211 &mut vtbl.path,
212 Path {
213 leading_colon,
214 segments: Default::default(),
215 },
216 );
217
218 for seg in old_path.segments.into_pairs().skip(1) {
219 match seg {
220 punctuated::Pair::Punctuated(p, punc) => {
221 vtbl.path.segments.push_value(p);
222 vtbl.path.segments.push_punct(punc);
223 }
224 punctuated::Pair::End(p) => {
225 vtbl.path.segments.push_value(p);
226 }
227 }
228 }
229
230 ext_traits.insert(tr.ident.clone(), (vtbl.path.clone(), tr.clone()));
231 } else {
232 let tr = store_traits
234 .get(&(vtbl.path.clone(), vtbl.raw_ident.clone()))
235 .or_else(|| {
236 store_exports.get(&vtbl.raw_ident).and_then(|p| {
237 vtbl.path = p.clone();
238 store_traits.get(&(p.clone(), vtbl.raw_ident.clone()))
239 })
240 });
241
242 if let Some(tr) = tr {
243 let old_path = std::mem::replace(&mut vtbl.path, crate_path.clone());
245 for seg in old_path.segments.into_pairs() {
246 match seg {
247 punctuated::Pair::Punctuated(p, punc) => {
248 vtbl.path.segments.push_value(p);
249 vtbl.path.segments.push_punct(punc);
250 }
251 punctuated::Pair::End(p) => {
252 vtbl.path.segments.push_value(p);
253 }
254 }
255 }
256 ext_traits.insert(tr.ident.clone(), (vtbl.path.clone(), tr.clone()));
257 } else {
258 eprintln!(
259 "Could not find external trait {}. Not changing paths.",
260 vtbl.raw_ident
261 );
262 }
263 }
264 }
265
266 let extra_filler_traits = if input.parse::<Token![,]>().is_ok() {
267 input.parse::<LitBool>()?.value
268 } else {
269 true
270 };
271
272 let cont_name = format_ident!("{}Container", name);
273
274 Ok(Self {
275 name,
276 cont_name,
277 generics,
278 mandatory_vtbl,
279 optional_vtbl,
280 ext_traits,
281 extra_filler_traits,
282 })
283 }
284}
285
286#[cfg(not(feature = "unstable"))]
288pub struct TraitGroupImpl {
289 ty: Type,
290 ty_generics: ParsedGenerics,
291 generics: ParsedGenerics,
292 group_path: Path,
293 group: Ident,
294 implemented_vtbl: Vec<TraitInfo>,
295 fwd_implemented_vtbl: Option<Vec<TraitInfo>>,
296}
297
298#[cfg(not(feature = "unstable"))]
299impl Parse for TraitGroupImpl {
300 fn parse(input: ParseStream) -> Result<Self> {
301 let mut ty: Type = input.parse()?;
302
303 let ty_gens = extract_generics(&mut ty);
306
307 let mut ty_generics = ParsedGenerics::from(ty_gens.as_ref());
308
309 input.parse::<Token![,]>()?;
310
311 let group = input.parse()?;
312
313 let (group_path, group, gens) = split_path_ident(&group)?;
314
315 let generics = ParsedGenerics::from(gens.as_ref());
316
317 let mut generics = match input.parse::<ParsedGenerics>() {
318 Ok(ParsedGenerics {
319 gen_where_bounds, ..
320 }) => {
321 parse_brace_content(input).ok();
322 ParsedGenerics {
323 gen_where_bounds,
324 ..generics
325 }
326 }
327 _ => generics,
328 };
329
330 generics.merge_and_remap(&mut ty_generics);
331
332 let implemented_vtbl = if input.parse::<Token![,]>().is_ok() {
333 let implemented_traits = parse_maybe_braced::<AliasPath>(input)?;
334
335 let mut implemented_vtbl: Vec<TraitInfo> = implemented_traits
336 .into_iter()
337 .map(AliasPath::prelude_remap)
338 .map(AliasPath::ext_abs_remap)
339 .map(From::from)
340 .collect();
341
342 implemented_vtbl.sort();
343
344 implemented_vtbl
345 } else {
346 vec![]
347 };
348
349 let fwd_implemented_vtbl = if input.parse::<Token![,]>().is_ok() {
350 let implemented_traits = parse_maybe_braced::<AliasPath>(input)?;
351
352 let mut implemented_vtbl: Vec<TraitInfo> = implemented_traits
353 .into_iter()
354 .map(AliasPath::prelude_remap)
355 .map(AliasPath::ext_abs_remap)
356 .map(From::from)
357 .collect();
358
359 implemented_vtbl.sort();
360
361 Some(implemented_vtbl)
362 } else {
363 None
364 };
365
366 ty_generics.replace_on_type(&mut ty);
367 ty_generics.extract_lifetimes(&ty);
368
369 Ok(Self {
370 ty,
371 ty_generics,
372 generics,
373 group_path,
374 group,
375 implemented_vtbl,
376 fwd_implemented_vtbl,
377 })
378 }
379}
380
381#[cfg(not(feature = "unstable"))]
382impl TraitGroupImpl {
383 #[cfg(feature = "unstable")]
387 pub fn implement_group(&self) -> TokenStream {
388 Default::default()
389 }
390
391 #[cfg(not(feature = "unstable"))]
392 pub fn implement_group(&self) -> TokenStream {
393 let crate_path = crate_path();
394
395 let ctx_bound = super::traits::ctx_bound();
396
397 let ty = &self.ty;
398
399 let group = &self.group;
400 let group_path = &self.group_path;
401 let ParsedGenerics { gen_use, .. } = &self.generics;
402
403 let ParsedGenerics {
404 gen_declare,
405 gen_where_bounds,
406 mut life_declare,
407 mut life_use,
408 ..
409 } = [&self.ty_generics, &self.generics]
410 .iter()
411 .copied()
412 .collect();
413
414 if life_use.is_empty() {
416 assert!(life_declare.is_empty());
417 let lifetime = Lifetime {
418 apostrophe: proc_macro2::Span::call_site(),
419 ident: format_ident!("cglue_a"),
420 };
421 life_use.push_value(lifetime.clone());
422 life_declare.push_value(LifetimeDef {
423 lifetime,
424 attrs: Default::default(),
425 bounds: Default::default(),
426 colon_token: Default::default(),
427 });
428 }
429
430 if !life_declare.trailing_punct() {
431 life_declare.push_punct(Default::default());
432 }
433
434 if !life_use.trailing_punct() {
435 life_use.push_punct(Default::default());
436 }
437
438 let first_life = life_use.first().unwrap();
440
441 let gen_lt_bounds = self.generics.declare_lt_for_all("e!(#first_life));
442 let gen_sabi_bounds = self.generics.declare_sabi_for_all(&crate_path);
443
444 let gen_where_bounds = quote! {
445 #gen_where_bounds
446 #gen_sabi_bounds
447 #gen_lt_bounds
448 };
449
450 let filler_trait = format_ident!("{}VtableFiller", group);
451 let vtable_type = format_ident!("{}Vtables", group);
452 let cont_name = format_ident!("{}Container", group);
453
454 let implemented_tables = TraitGroup::enable_opt_vtbls(self.implemented_vtbl.iter());
455 let vtbl_where_bounds = TraitGroup::vtbl_where_bounds(
456 self.implemented_vtbl.iter(),
457 &cont_name,
458 quote!(CGlueInst),
459 quote!(CGlueCtx),
460 &self.generics,
461 Some(quote!(Self)).as_ref(),
462 first_life,
463 );
464
465 let gen = quote! {
466 impl<#life_declare CGlueInst: ::core::ops::Deref<Target = #ty>, CGlueCtx: #ctx_bound, #gen_declare>
467 #group_path #filler_trait<#life_use CGlueInst, CGlueCtx, #gen_use> for #ty
468 where #gen_where_bounds #vtbl_where_bounds {
469 fn fill_table(table: #group_path #vtable_type<#life_use CGlueInst, CGlueCtx, #gen_use>) -> #group_path #vtable_type<#life_use CGlueInst, CGlueCtx, #gen_use> {
470 table #implemented_tables
471 }
472 }
473 };
474
475 if let Some(fwd_vtbl) = &self.fwd_implemented_vtbl {
476 let fwd_filler_trait = format_ident!("{}FwdVtableFiller", group);
477
478 let fwd_ty = quote!(#crate_path::forward::Fwd<&#first_life mut #ty>);
479
480 let implemented_tables = TraitGroup::enable_opt_vtbls(fwd_vtbl.iter());
481 let vtbl_where_bounds = TraitGroup::vtbl_where_bounds(
482 fwd_vtbl.iter(),
483 &cont_name,
484 quote!(CGlueInst),
485 quote!(CGlueCtx),
486 &self.generics,
487 Some(quote!(Self)).as_ref(),
488 first_life,
489 );
490
491 quote! {
492 #gen
493
494 impl<#life_declare CGlueInst: ::core::ops::Deref<Target = #fwd_ty>, CGlueCtx: #ctx_bound, #gen_declare>
495 #group_path #fwd_filler_trait<#life_use CGlueInst, CGlueCtx, #gen_use> for #ty
496 where
497 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #crate_path::trait_group::CGlueObjBase,
498 #gen_where_bounds #vtbl_where_bounds
499 {
500 fn fill_fwd_table(table: #group_path #vtable_type<#life_use CGlueInst, CGlueCtx, #gen_use>) -> #group_path #vtable_type<#life_use CGlueInst, CGlueCtx, #gen_use> {
501 table #implemented_tables
502 }
503 }
504 }
505 } else {
506 gen
507 }
508 }
509}
510
511pub struct TraitCastGroup {
512 name: TokenStream,
513 needed_vtbls: Vec<TraitInfo>,
514}
515
516pub enum CastType {
517 Cast,
518 AsRef,
519 AsMut,
520 Into,
521 OnlyCheck,
522}
523
524impl Parse for TraitCastGroup {
525 fn parse(input: ParseStream) -> Result<Self> {
526 let name;
527
528 if let Ok(expr) = input.parse::<Expr>() {
529 name = quote!(#expr);
530 } else {
531 name = input.parse::<Ident>()?.into_token_stream();
532 }
533
534 let implemented_traits = input.parse::<TypeImplTrait>()?;
535
536 let mut needed_vtbls: Vec<TraitInfo> = implemented_traits
537 .bounds
538 .into_iter()
539 .filter_map(|b| match b {
540 TypeParamBound::Trait(tr) => Some(AliasPath {
541 path: tr.path,
542 alias: None,
543 }),
544 _ => None,
545 })
546 .map(From::from)
547 .collect();
548
549 needed_vtbls.sort();
550
551 Ok(Self { name, needed_vtbls })
552 }
553}
554
555impl TraitCastGroup {
556 pub fn cast_group(&self, cast: CastType) -> TokenStream {
560 let prefix = match cast {
561 CastType::Cast => "cast",
562 CastType::AsRef => "as_ref",
563 CastType::AsMut => "as_mut",
564 CastType::Into => "into",
565 CastType::OnlyCheck => "check",
566 };
567
568 let name = &self.name;
569 let func_name = TraitGroup::optional_func_name(prefix, self.needed_vtbls.iter());
570
571 quote! {
572 (#name).#func_name()
573 }
574 }
575}
576
577impl TraitGroup {
578 pub fn optional_group_ident<'a>(
586 name: &Ident,
587 postfix: &str,
588 traits: impl Iterator<Item = &'a TraitInfo>,
589 ) -> Ident {
590 let mut all_traits = String::new();
591
592 for TraitInfo { name_ident, .. } in traits {
593 all_traits.push_str(&name_ident.to_string());
594 }
595
596 format_ident!("{}{}With{}", name, postfix, all_traits)
597 }
598
599 pub fn optional_func_name<'a>(
606 prefix: &str,
607 lc_names: impl Iterator<Item = &'a TraitInfo>,
608 ) -> Ident {
609 let mut ident = format_ident!("{}_impl", prefix);
610
611 for TraitInfo { lc_name, .. } in lc_names {
612 ident = format_ident!("{}_{}", ident, lc_name);
613 }
614
615 ident
616 }
617
618 pub fn enable_opt_vtbls<'a>(iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
624 let mut ret = TokenStream::new();
625
626 for TraitInfo {
627 enable_vtbl_name, ..
628 } in iter
629 {
630 ret.extend(quote!(.#enable_vtbl_name()));
631 }
632
633 ret
634 }
635
636 pub fn create_group(&self) -> TokenStream {
641 let crate_path = crate::util::crate_path();
643
644 let ctx_bound = super::traits::ctx_bound();
645
646 let trg_path: TokenStream = quote!(#crate_path::trait_group);
647
648 let c_void = crate::util::void_type();
649
650 let name = &self.name;
651 let cont_name = &self.cont_name;
652
653 let ParsedGenerics {
654 gen_declare,
655 gen_use,
656 gen_where_bounds,
657 ..
658 } = &self.generics;
659
660 let gen_lt_bounds = self.generics.declare_lt_for_all("e!('cglue_a));
661 let gen_sabi_bounds = self.generics.declare_sabi_for_all(&crate_path);
662
663 let gen_where_bounds_base = quote! {
665 #gen_where_bounds
666 #gen_lt_bounds
667 };
668
669 let gen_where_bounds = quote! {
671 #gen_where_bounds_base
672 #gen_sabi_bounds
673 };
674
675 let cglue_a_lifetime = Lifetime {
676 apostrophe: proc_macro2::Span::call_site(),
677 ident: format_ident!("cglue_a"),
678 };
679
680 let mandatory_vtbl_defs = self.mandatory_vtbl_defs(self.mandatory_vtbl.iter());
681 let optional_vtbl_defs = self.optional_vtbl_defs(quote!(CGlueInst), quote!(CGlueCtx));
682 let optional_vtbl_defs_boxed = self.optional_vtbl_defs(
683 quote!(#crate_path::boxed::CBox<'cglue_a, CGlueT>),
684 quote!(#crate_path::trait_group::NoContext),
685 );
686
687 let mand_vtbl_default = self.mandatory_vtbl_defaults();
688 let mand_ret_tmp_default = self.mandatory_ret_tmp_defaults();
689 let full_opt_ret_tmp_default = Self::ret_tmp_defaults(self.optional_vtbl.iter());
690 let default_opt_vtbl_list = self.default_opt_vtbl_list();
691 let mand_vtbl_list = self.vtbl_list(self.mandatory_vtbl.iter());
692 let full_opt_vtbl_list = self.vtbl_list(self.optional_vtbl.iter());
693 let mandatory_as_ref_impls = self.mandatory_as_ref_impls(&trg_path);
694
695 let get_container_impl = self.get_container_impl(name, &trg_path, &self.generics);
696
697 let mandatory_internal_trait_impls = self.internal_trait_impls(
698 name,
699 self.mandatory_vtbl.iter(),
700 &self.generics,
701 &crate_path,
702 );
703 let vtbl_where_bounds = Self::vtbl_where_bounds(
704 self.mandatory_vtbl.iter(),
705 cont_name,
706 quote!(CGlueInst),
707 quote!(CGlueCtx),
708 &self.generics,
709 None,
710 &cglue_a_lifetime,
711 );
712 let vtbl_where_bounds_noctx = Self::vtbl_where_bounds(
713 self.mandatory_vtbl.iter(),
714 cont_name,
715 quote!(CGlueInst),
716 quote!(#trg_path::NoContext),
717 &self.generics,
718 None,
719 &cglue_a_lifetime,
720 );
721 let vtbl_where_bounds_boxed = Self::vtbl_where_bounds(
722 self.mandatory_vtbl.iter(),
723 cont_name,
724 quote!(#crate_path::boxed::CBox<'cglue_a, CGlueT>),
725 quote!(#crate_path::trait_group::NoContext),
726 &self.generics,
727 None,
728 &cglue_a_lifetime,
729 );
730 let vtbl_where_bounds_ctxboxed = Self::vtbl_where_bounds(
731 self.mandatory_vtbl.iter(),
732 cont_name,
733 quote!(#crate_path::boxed::CBox<'cglue_a, CGlueT>),
734 quote!(CGlueCtx),
735 &self.generics,
736 None,
737 &cglue_a_lifetime,
738 );
739 let ret_tmp_defs = self.ret_tmp_defs(self.optional_vtbl.iter());
740
741 let mut enable_funcs = TokenStream::new();
742 let mut enable_funcs_vtbl = TokenStream::new();
743
744 #[cfg(feature = "layout_checks")]
745 let derive_layouts = quote!(#[derive(::abi_stable::StableAbi)]);
746 #[cfg(not(feature = "layout_checks"))]
747 let derive_layouts = quote!();
748
749 let all_gen_use = &gen_use;
750
751 let fill_rest = if self.optional_vtbl.len() + self.mandatory_vtbl.len() > 1 {
753 quote!(..self)
754 } else {
755 quote!()
756 };
757
758 for TraitInfo {
759 enable_vtbl_name,
760 vtbl_typename,
761 vtbl_name,
762 path,
763 generics: ParsedGenerics { gen_use, .. },
764 assocs: ParsedGenerics {
765 gen_use: assoc_use, ..
766 },
767 ..
768 } in &self.optional_vtbl
769 {
770 for (funcs, fill_rest) in &mut [
771 (&mut enable_funcs, "e!(..self)),
772 (&mut enable_funcs_vtbl, &fill_rest),
773 ] {
774 funcs.extend(quote! {
775 pub fn #enable_vtbl_name (self) -> Self
776 where &'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use>: Default {
777 Self {
778 #vtbl_name: Some(Default::default()),#fill_rest
779 }
780 }
781 });
782 }
783 }
784
785 let mut trait_funcs = TokenStream::new();
786
787 let mut opt_structs = TokenStream::new();
788 let mut opt_struct_imports = TokenStream::new();
789
790 let impl_traits =
791 self.impl_traits(self.mandatory_vtbl.iter().chain(self.optional_vtbl.iter()));
792
793 let base_doc = format!(
794 " Trait group potentially implementing `{}` traits.",
795 impl_traits
796 );
797 let trback_doc = format!("be transformed back into `{}` without losing data.", name);
798 let new_doc = format!(" Create new instance of {}.", name);
799
800 let base_name = format_ident!("{}Base", name);
801 let base_name_ref = format_ident!("{}BaseRef", name);
802 let base_name_ctx_ref = format_ident!("{}BaseCtxRef", name);
803 let base_name_arc_ref = format_ident!("{}BaseArcRef", name);
804 let base_name_mut = format_ident!("{}BaseMut", name);
805 let base_name_ctx_mut = format_ident!("{}BaseCtxMut", name);
806 let base_name_arc_mut = format_ident!("{}BaseArcMut", name);
807 let base_name_boxed = format_ident!("{}BaseBox", name);
808 let base_name_arc_box = format_ident!("{}BaseArcBox", name);
809 let base_name_ctx_box = format_ident!("{}BaseCtxBox", name);
810 let opaque_name_ref = format_ident!("{}Ref", name);
811 let opaque_name_ctx_ref = format_ident!("{}CtxRef", name);
812 let opaque_name_arc_ref = format_ident!("{}ArcRef", name);
813 let opaque_name_mut = format_ident!("{}Mut", name);
814 let opaque_name_ctx_mut = format_ident!("{}CtxMut", name);
815 let opaque_name_arc_mut = format_ident!("{}ArcMut", name);
816 let opaque_name_boxed = format_ident!("{}Box", name);
817 let opaque_name_arc_box = format_ident!("{}ArcBox", name);
818 let opaque_name_ctx_box = format_ident!("{}CtxBox", name);
819
820 #[cfg(not(feature = "unstable"))]
821 let filler_trait = format_ident!("{}VtableFiller", name);
822 #[cfg(not(feature = "unstable"))]
823 let fwd_filler_trait = format_ident!("{}FwdVtableFiller", name);
824 let vtable_type = format_ident!("{}Vtables", name);
825
826 for traits in self
827 .optional_vtbl
828 .iter()
829 .powerset()
830 .filter(|v| !v.is_empty())
831 {
832 let func_name = Self::optional_func_name("cast", traits.iter().copied());
833 let func_name_final = Self::optional_func_name("into", traits.iter().copied());
834 let func_name_check = Self::optional_func_name("check", traits.iter().copied());
835 let func_name_mut = Self::optional_func_name("as_mut", traits.iter().copied());
836 let func_name_ref = Self::optional_func_name("as_ref", traits.iter().copied());
837 let opt_final_name = Self::optional_group_ident(name, "Final", traits.iter().copied());
838 let opt_name = Self::optional_group_ident(name, "", traits.iter().copied());
839 let opt_vtbl_defs = self.mandatory_vtbl_defs(traits.iter().copied());
840 let opt_mixed_vtbl_defs = self.mixed_opt_vtbl_defs(traits.iter().copied());
841
842 let opt_vtbl_list = self.vtbl_list(traits.iter().copied());
843 let opt_vtbl_unwrap = self.vtbl_unwrap_list(traits.iter().copied());
844 let opt_vtbl_unwrap_validate = self.vtbl_unwrap_validate(traits.iter().copied());
845
846 let mixed_opt_vtbl_unwrap = self.mixed_opt_vtbl_unwrap_list(traits.iter().copied());
847
848 let get_container_impl = self.get_container_impl(&opt_name, &trg_path, &self.generics);
849
850 let opt_as_ref_impls = self.as_ref_impls(
851 &opt_name,
852 self.mandatory_vtbl.iter().chain(traits.iter().copied()),
853 &self.generics,
854 &trg_path,
855 );
856
857 let opt_internal_trait_impls = self.internal_trait_impls(
858 &opt_name,
859 self.mandatory_vtbl.iter().chain(traits.iter().copied()),
860 &self.generics,
861 &crate_path,
862 );
863
864 let get_container_impl_final =
865 self.get_container_impl(&opt_final_name, &trg_path, &self.generics);
866
867 let opt_final_as_ref_impls = self.as_ref_impls(
868 &opt_final_name,
869 self.mandatory_vtbl.iter().chain(traits.iter().copied()),
870 &self.generics,
871 &trg_path,
872 );
873
874 let opt_final_internal_trait_impls = self.internal_trait_impls(
875 &opt_final_name,
876 self.mandatory_vtbl.iter().chain(traits.iter().copied()),
877 &self.generics,
878 &crate_path,
879 );
880
881 let impl_traits =
882 self.impl_traits(self.mandatory_vtbl.iter().chain(traits.iter().copied()));
883
884 let opt_final_doc = format!(
885 " Final {} variant with `{}` implemented.",
886 name, &impl_traits
887 );
888 let opt_final_doc2 = format!(
889 " Retrieve this type using [`{}`]({}::{}) function.",
890 func_name_final, name, func_name_final
891 );
892
893 let opt_doc = format!(
894 " Concrete {} variant with `{}` implemented.",
895 name, &impl_traits
896 );
897 let opt_doc2 = format!(" Retrieve this type using one of [`{}`]({}::{}), [`{}`]({}::{}), or [`{}`]({}::{}) functions.", func_name, name, func_name, func_name_mut, name, func_name_mut, func_name_ref, name, func_name_ref);
898
899 opt_struct_imports.extend(quote! {
902 #opt_final_name,
903 #opt_name,
904 });
905
906 opt_structs.extend(quote! {
907
908 #[doc = #opt_final_doc]
911 #[doc = #opt_final_doc2]
913 #[repr(C)]
914 #derive_layouts
915 pub struct #opt_final_name<'cglue_a, CGlueInst: 'cglue_a, CGlueCtx: #ctx_bound, #gen_declare>
916 where
917 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
918 #gen_where_bounds_base
919 {
920 #mandatory_vtbl_defs
921 #opt_vtbl_defs
922 container: #cont_name<CGlueInst, CGlueCtx, #gen_use>,
923 }
924
925 #get_container_impl_final
926
927 #opt_final_as_ref_impls
928
929 #opt_final_internal_trait_impls
930
931 #[doc = #opt_doc]
934 #[doc = #opt_doc2]
936 #[repr(C)]
937 #derive_layouts
938 pub struct #opt_name<'cglue_a, CGlueInst: 'cglue_a, CGlueCtx: #ctx_bound, #gen_declare>
939 where
940 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
941 #gen_where_bounds_base
942 {
943 #mandatory_vtbl_defs
944 #opt_mixed_vtbl_defs
945 container: #cont_name<CGlueInst, CGlueCtx, #gen_use>,
946 }
947
948 unsafe impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare>
949 #trg_path::Opaquable for #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
950 where
951 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
952 #gen_where_bounds
953 {
954 type OpaqueTarget = #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>;
955 }
956
957 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare>
958 From<#opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>> for #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
959 where
960 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
961 #gen_where_bounds
962 {
963 fn from(input: #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>) -> Self {
964 #trg_path::Opaquable::into_opaque(input)
965 }
966 }
967
968 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare> #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
969 where Self: #trg_path::Opaquable,
970 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
971 #gen_where_bounds
972 {
973 pub fn upcast(self) -> <Self as #trg_path::Opaquable>::OpaqueTarget {
975 #trg_path::Opaquable::into_opaque(self)
976 }
977 }
978
979 #get_container_impl
980
981 #opt_as_ref_impls
982
983 #opt_internal_trait_impls
984 });
985
986 let func_final_doc1 = format!(
987 " Retrieve a final {} variant that implements `{}`.",
988 name, impl_traits
989 );
990 let func_final_doc2 = format!(
991 " This consumes the `{}`, and outputs `Some(impl {})`, if all types are present.",
992 name, impl_traits
993 );
994
995 let func_doc1 = format!(
996 " Retrieve a concrete {} variant that implements `{}`.",
997 name, impl_traits
998 );
999 let func_doc2 = format!(" This consumes the `{}`, and outputs `Some(impl {})`, if all types are present. It is possible to cast this type back with the `From` implementation.", name, impl_traits);
1000
1001 let func_check_doc1 = format!(" Check whether {} implements `{}`.", name, impl_traits);
1002 let func_check_doc2 =
1003 " If this check returns true, it is safe to run consuming conversion operations."
1004 .to_string();
1005
1006 let func_mut_doc1 = format!(
1007 " Retrieve mutable reference to a concrete {} variant that implements `{}`.",
1008 name, impl_traits
1009 );
1010 let func_ref_doc1 = format!(
1011 " Retrieve immutable reference to a concrete {} variant that implements `{}`.",
1012 name, impl_traits
1013 );
1014
1015 trait_funcs.extend(quote! {
1016 #[doc = #func_check_doc1]
1017 #[doc = #func_check_doc2]
1019 pub fn #func_name_check(&self) -> bool
1020 where #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>: 'cglue_a + #impl_traits
1021 {
1022 self.#func_name_ref().is_some()
1023 }
1024
1025 #[doc = #func_final_doc1]
1026 #[doc = #func_final_doc2]
1028 pub fn #func_name_final(self) -> ::core::option::Option<impl 'cglue_a + #impl_traits>
1029 where #opt_final_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>: 'cglue_a + #impl_traits
1030 {
1031 let #name {
1032 container,
1033 #mand_vtbl_list
1034 #opt_vtbl_list
1035 ..
1036 } = self;
1037
1038 Some(#opt_final_name {
1039 container,
1040 #mand_vtbl_list
1041 #opt_vtbl_unwrap
1042 })
1043 }
1044
1045 #[doc = #func_doc1]
1046 #[doc = #func_doc2]
1048 pub fn #func_name(self) -> ::core::option::Option<#opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>>
1049 where #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>: 'cglue_a + #impl_traits
1050 {
1051 let #name {
1052 container,
1053 #mand_vtbl_list
1054 #full_opt_vtbl_list
1055 } = self;
1056
1057 Some(#opt_name {
1058 container,
1059 #mand_vtbl_list
1060 #mixed_opt_vtbl_unwrap
1061 })
1062 }
1063
1064 #[doc = #func_mut_doc1]
1065 pub fn #func_name_mut<'b>(&'b mut self) -> ::core::option::Option<&'b mut (impl 'cglue_a + #impl_traits)>
1066 where #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>: 'cglue_a + #impl_traits
1067 {
1068 let #name {
1069 container,
1070 #mand_vtbl_list
1071 #opt_vtbl_list
1072 ..
1073 } = self;
1074
1075 let _ = (#opt_vtbl_unwrap_validate);
1076
1077 unsafe {
1083 (self as *mut Self as *mut #opt_name<CGlueInst, CGlueCtx, #gen_use>).as_mut()
1084 }
1085 }
1086
1087 #[doc = #func_ref_doc1]
1088 pub fn #func_name_ref<'b>(&'b self) -> ::core::option::Option<&'b (impl 'cglue_a + #impl_traits)>
1089 where #opt_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>: 'cglue_a + #impl_traits
1090 {
1091 let #name {
1092 #mand_vtbl_list
1093 #opt_vtbl_list
1094 ..
1095 } = self;
1096
1097 let _ = (#opt_vtbl_unwrap_validate);
1098
1099 unsafe {
1105 (self as *const Self as *const #opt_name<CGlueInst, CGlueCtx, #gen_use>).as_ref()
1106 }
1107 }
1108 });
1109 }
1110
1111 #[cfg(not(feature = "unstable"))]
1112 let (extra_filler_traits, filler_trait_imports) = if self.extra_filler_traits {
1113 let traits = quote! {
1114 pub trait #fwd_filler_trait<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #gen_declare>: 'cglue_a + Sized
1115 where
1116 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1117 #gen_where_bounds
1118 {
1119 fn fill_fwd_table(table: #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>) -> #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>;
1120 }
1121
1122 impl<'cglue_a, CGlueInst: ::core::ops::Deref<Target = #crate_path::forward::Fwd<&'cglue_a mut CGlueT>>, CGlueT, CGlueCtx: #ctx_bound, #gen_declare>
1123 #filler_trait<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1124 for #crate_path::forward::Fwd<&'cglue_a mut CGlueT>
1125 where
1126 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1127 CGlueT: #fwd_filler_trait<'cglue_a, CGlueInst, CGlueCtx, #gen_use>,
1128 #gen_where_bounds
1129 {
1130 fn fill_table(table: #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>) -> #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use> {
1131 CGlueT::fill_fwd_table(table)
1132 }
1133 }
1134 };
1135
1136 let imports = quote! {
1137 #filler_trait,
1138 #fwd_filler_trait,
1139 };
1140
1141 (traits, imports)
1142 } else {
1143 (quote!(), quote!(#filler_trait,))
1144 };
1145
1146 #[cfg(feature = "unstable")]
1147 let filler_trait_imports = quote!();
1148
1149 let submod_name = format_ident!("cglue_{}", name.to_string().to_lowercase());
1150
1151 let cglue_obj_impl = self.cglue_obj_impl(&trg_path, &self.generics);
1152
1153 #[cfg(feature = "unstable")]
1154 let cglue_inst_filler_trait_bound = quote!();
1155 #[cfg(not(feature = "unstable"))]
1156 let cglue_inst_filler_trait_bound =
1157 quote!(CGlueInst::Target: #filler_trait<'cglue_a, CGlueInst, CGlueCtx, #gen_use>,);
1158 #[cfg(feature = "unstable")]
1159 let create_vtbl = quote!(Default::default());
1160 #[cfg(not(feature = "unstable"))]
1161 let create_vtbl = quote!(CGlueInst::Target::fill_table(Default::default()));
1162
1163 #[cfg(feature = "unstable")]
1164 let filler_trait_impl = quote!();
1165 #[cfg(not(feature = "unstable"))]
1166 let filler_trait_impl = quote! {
1167 pub trait #filler_trait<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare>: Sized
1168 where
1169 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1170 #gen_where_bounds
1171 {
1172 fn fill_table(table: #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>) -> #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>;
1173 }
1174
1175 #extra_filler_traits
1176 };
1177
1178 quote! {
1179
1180 #[doc(hidden)]
1181 pub use #submod_name::*;
1182
1183 pub mod #submod_name {
1184 use super::*;
1185
1186 pub use cglue_internal::{
1187 #name,
1188 #vtable_type,
1189 #filler_trait_imports
1190 #base_name,
1191 #base_name_ref,
1192 #base_name_ctx_ref,
1193 #base_name_arc_ref,
1194 #base_name_mut,
1195 #base_name_ctx_mut,
1196 #base_name_arc_mut,
1197 #base_name_boxed,
1198 #base_name_arc_box,
1199 #base_name_ctx_box,
1200 #opaque_name_ref,
1201 #opaque_name_ctx_ref,
1202 #opaque_name_arc_ref,
1203 #opaque_name_mut,
1204 #opaque_name_ctx_mut,
1205 #opaque_name_arc_mut,
1206 #opaque_name_boxed,
1207 #opaque_name_arc_box,
1208 #opaque_name_ctx_box,
1209 #cont_name,
1210 #opt_struct_imports
1211 };
1212
1213 mod cglue_internal {
1214 use super::*;
1215
1216 #[repr(C)]
1217 #[doc = #base_doc]
1218 #[doc = #trback_doc]
1229 #derive_layouts
1234 pub struct #name<'cglue_a, CGlueInst: 'cglue_a, CGlueCtx: #ctx_bound, #gen_declare>
1235 where
1236 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1237 #gen_where_bounds_base
1238 {
1239 #mandatory_vtbl_defs
1240 #optional_vtbl_defs
1241 container: #cont_name<CGlueInst, CGlueCtx, #gen_use>,
1242 }
1243
1244 #get_container_impl
1245
1246 #[repr(C)]
1247 #derive_layouts
1248 pub struct #cont_name<CGlueInst, CGlueCtx: #ctx_bound, #gen_declare>
1249 {
1250 instance: CGlueInst,
1251 context: CGlueCtx,
1252 #ret_tmp_defs
1253 }
1254
1255 #cglue_obj_impl
1256
1257 unsafe impl<CGlueInst: #trg_path::Opaquable, CGlueCtx: #ctx_bound, #gen_declare>
1258 #trg_path::Opaquable for #cont_name<CGlueInst, CGlueCtx, #gen_use>
1259 {
1260 type OpaqueTarget = #cont_name<CGlueInst::OpaqueTarget, CGlueCtx, #gen_use>;
1261 }
1262
1263 #[repr(C)]
1264 #derive_layouts
1265 pub struct #vtable_type<'cglue_a, CGlueInst: 'cglue_a, CGlueCtx: #ctx_bound, #gen_declare>
1266 where
1267 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1268 #gen_where_bounds_base
1269 {
1270 #mandatory_vtbl_defs
1271 #optional_vtbl_defs
1272 }
1273
1274 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare> Default
1275 for #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1276 where
1277 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1278 #vtbl_where_bounds #gen_where_bounds
1279 {
1280 fn default() -> Self {
1281 Self {
1282 #mand_vtbl_default
1283 #default_opt_vtbl_list
1284 }
1285 }
1286 }
1287
1288 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare> #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1289 where
1290 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1291 #gen_where_bounds
1292 {
1293 #enable_funcs
1294 }
1295
1296 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare> #vtable_type<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1297 where
1298 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1299 #gen_where_bounds
1300 {
1301 #enable_funcs_vtbl
1302 }
1303
1304 #filler_trait_impl
1305
1306 pub type #base_name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1307 = #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>;
1308
1309 pub type #base_name_boxed<'cglue_a, CGlueT, #gen_use>
1310 = #base_name_ctx_box<'cglue_a, CGlueT, #crate_path::trait_group::NoContext, #gen_use>;
1311
1312 pub type #base_name_ctx_box<'cglue_a, CGlueT, CGlueCtx, #gen_use>
1313 = #name<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx, #gen_use>;
1314
1315 pub type #base_name_arc_box<'cglue_a, CGlueT, CGlueArcTy, #gen_use>
1316 = #base_name_ctx_box<'cglue_a, CGlueT, #crate_path::arc::CArc<CGlueArcTy>, #gen_use>;
1317
1318 pub type #base_name_ref<'cglue_a, CGlueT, #gen_use>
1319 = #name<'cglue_a, &'cglue_a CGlueT, #crate_path::trait_group::NoContext, #gen_use>;
1320
1321 pub type #base_name_ctx_ref<'cglue_a, CGlueT, CGlueCtx, #gen_use>
1322 = #name<'cglue_a, &'cglue_a CGlueT, CGlueCtx, #gen_use>;
1323
1324 pub type #base_name_arc_ref<'cglue_a, CGlueT, CGlueArcTy, #gen_use>
1325 = #name<'cglue_a, &'cglue_a CGlueT, #crate_path::arc::CArc<CGlueArcTy>, #gen_use>;
1326
1327 pub type #base_name_mut<'cglue_a, CGlueT, #gen_use>
1328 = #name<'cglue_a, &'cglue_a mut CGlueT, #crate_path::trait_group::NoContext, #gen_use>;
1329
1330 pub type #base_name_ctx_mut<'cglue_a, CGlueT, CGlueCtx, #gen_use>
1331 = #name<'cglue_a, &'cglue_a mut CGlueT, CGlueCtx, #gen_use>;
1332
1333 pub type #base_name_arc_mut<'cglue_a, CGlueT, CGlueArcTy, #gen_use>
1334 = #name<'cglue_a, &'cglue_a mut CGlueT, #crate_path::arc::CArc<CGlueArcTy>, #gen_use>;
1335
1336 pub type #opaque_name_boxed<'cglue_a, #gen_use>
1337 = #base_name_boxed<'cglue_a, #c_void, #gen_use>;
1338
1339 pub type #opaque_name_ref<'cglue_a, #gen_use>
1340 = #base_name_ref<'cglue_a, #c_void, #gen_use>;
1341
1342 pub type #opaque_name_ctx_ref<'cglue_a, CGlueCtx, #gen_use>
1343 = #base_name_ctx_ref<'cglue_a, #c_void, CGlueCtx, #gen_use>;
1344
1345 pub type #opaque_name_arc_ref<'cglue_a, #gen_use>
1346 = #base_name_arc_ref<'cglue_a, #c_void, #c_void, #gen_use>;
1347
1348 pub type #opaque_name_mut<'cglue_a, #gen_use>
1349 = #base_name_mut<'cglue_a, #c_void, #gen_use>;
1350
1351 pub type #opaque_name_ctx_mut<'cglue_a, CGlueCtx, #gen_use>
1352 = #base_name_ctx_mut<'cglue_a, #c_void, CGlueCtx, #gen_use>;
1353
1354 pub type #opaque_name_arc_mut<'cglue_a, #gen_use>
1355 = #base_name_arc_mut<'cglue_a, #c_void, #c_void, #gen_use>;
1356
1357 pub type #opaque_name_ctx_box<'cglue_a, CGlueCtx, #gen_use>
1358 = #base_name_ctx_box<'cglue_a, #c_void, CGlueCtx, #gen_use>;
1359
1360 pub type #opaque_name_arc_box<'cglue_a, #gen_use>
1361 = #base_name_arc_box<'cglue_a, #c_void, #c_void, #gen_use>;
1362
1363
1364 impl<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #gen_declare>
1365 From<(CGlueInst, CGlueCtx)> for #cont_name<CGlueInst, CGlueCtx, #gen_use>
1366 where
1367 Self: #trg_path::CGlueObjBase
1368 {
1369 fn from((instance, context): (CGlueInst, CGlueCtx)) -> Self {
1370 Self {
1371 instance,
1372 context,
1373 #mand_ret_tmp_default
1374 #full_opt_ret_tmp_default
1375 }
1376 }
1377 }
1378
1379 impl<'cglue_a, CGlueT, CGlueCtx: #ctx_bound, #gen_declare>
1380 From<(CGlueT, CGlueCtx)> for #cont_name<#crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx, #gen_use>
1381 where
1382 Self: #trg_path::CGlueObjBase
1383 {
1384 fn from((this, context): (CGlueT, CGlueCtx)) -> Self {
1385 Self::from((#crate_path::boxed::CBox::from(this), context))
1386 }
1387 }
1388
1389 impl<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #gen_declare>
1390 From<#cont_name<CGlueInst, CGlueCtx, #gen_use>> for #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1391 where
1392 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1393 #cglue_inst_filler_trait_bound
1394 #vtbl_where_bounds #gen_where_bounds
1395 {
1396 fn from(container: #cont_name<CGlueInst, CGlueCtx, #gen_use>) -> Self {
1397 let vtbl = #create_vtbl;
1398
1399 let #vtable_type {
1400 #mand_vtbl_list
1401 #full_opt_vtbl_list
1402 } = vtbl;
1403
1404 Self {
1405 container,
1406 #mand_vtbl_list
1407 #full_opt_vtbl_list
1408 }
1409 }
1410 }
1411
1412 impl<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #gen_declare>
1413 From<(CGlueInst, CGlueCtx)> for #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1414 where
1415 Self: From<#cont_name<CGlueInst, CGlueCtx, #gen_use>>,
1416 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1417 #vtbl_where_bounds #gen_where_bounds
1418 {
1419 fn from((instance, context): (CGlueInst, CGlueCtx)) -> Self {
1420 Self::from(#cont_name::from((instance, context)))
1421 }
1422 }
1423
1424 impl<'cglue_a, CGlueT, #gen_declare>
1425 From<CGlueT> for #name<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, #crate_path::trait_group::NoContext, #gen_use>
1426 where
1427 Self: From<(#crate_path::boxed::CBox<'cglue_a, CGlueT>, #crate_path::trait_group::NoContext)>,
1428 #vtbl_where_bounds_boxed #gen_where_bounds
1429 {
1430 fn from(instance: CGlueT) -> Self {
1431 Self::from((#crate_path::boxed::CBox::from(instance), Default::default()))
1432 }
1433 }
1434
1435 impl<'cglue_a, CGlueInst: core::ops::Deref, #gen_declare> From<CGlueInst>
1436 for #name<'cglue_a, CGlueInst, #trg_path::NoContext, #gen_use>
1437 where
1438 Self: From<(CGlueInst, #crate_path::trait_group::NoContext)>,
1439 #cont_name<CGlueInst, #trg_path::NoContext, #gen_use>: #trg_path::CGlueObjBase,
1440 #vtbl_where_bounds_noctx #gen_where_bounds
1441 {
1442 fn from(instance: CGlueInst) -> Self {
1443 Self::from((instance, Default::default()))
1444 }
1445 }
1446
1447 impl<'cglue_a, CGlueT, CGlueCtx: #ctx_bound, #gen_declare> From<(CGlueT, CGlueCtx)>
1448 for #name<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx, #gen_use>
1449 where
1450 Self: From<(#crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx)>,
1451 #cont_name<#crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1452 #vtbl_where_bounds_ctxboxed #gen_where_bounds
1453 {
1454 fn from((this, context): (CGlueT, CGlueCtx)) -> Self {
1455 Self::from((#crate_path::boxed::CBox::from(this), context))
1456 }
1457 }
1458
1459 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_declare>
1460 #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1461 where
1462 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1463 #vtbl_where_bounds #gen_where_bounds
1464 {
1465 #[doc = #new_doc]
1466 pub fn new(instance: CGlueInst, context: CGlueCtx, #optional_vtbl_defs) -> Self
1467 where #vtbl_where_bounds
1468 {
1469 Self {
1470 container: #cont_name {
1471 instance,
1472 context,
1473 #mand_ret_tmp_default
1474 #full_opt_ret_tmp_default
1475 },
1476 #mand_vtbl_default
1477 #full_opt_vtbl_list
1478 }
1479 }
1480 }
1481
1482 impl<'cglue_a, CGlueT, #gen_declare> #name<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, #crate_path::trait_group::NoContext, #gen_use>
1483 where #gen_where_bounds
1484 {
1485 #[doc = #new_doc]
1486 pub fn new_boxed(this: CGlueT, #optional_vtbl_defs_boxed) -> Self
1489 where #vtbl_where_bounds_boxed
1490 {
1491 Self::new(From::from(this), Default::default(), #full_opt_vtbl_list)
1492 }
1493 }
1494
1495 unsafe impl<'cglue_a, CGlueInst: #trg_path::Opaquable, CGlueCtx: #ctx_bound, #gen_declare>
1499 #trg_path::Opaquable for #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1500 where
1501 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1502 #cont_name<CGlueInst::OpaqueTarget, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1503 #gen_where_bounds
1504 {
1505 type OpaqueTarget = #name<'cglue_a, CGlueInst::OpaqueTarget, CGlueCtx, #gen_use>;
1506 }
1507
1508 impl<
1509 'cglue_a,
1510 CGlueInst, CGlueCtx: #ctx_bound,
1512 #gen_declare
1513 >
1514 #name<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1515 where
1516 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1517 #gen_where_bounds
1518 {
1519 #trait_funcs
1520 }
1521
1522 #mandatory_as_ref_impls
1523
1524 #mandatory_internal_trait_impls
1525
1526 #opt_structs
1527 }
1528 }
1529 }
1530 }
1531
1532 fn internal_trait_impls<'a>(
1533 &'a self,
1534 self_ident: &Ident,
1535 iter: impl Iterator<Item = &'a TraitInfo>,
1536 all_generics: &ParsedGenerics,
1537 crate_path: &TokenStream,
1538 ) -> TokenStream {
1539 let mut ret = TokenStream::new();
1540
1541 let cont_name = &self.cont_name;
1542
1543 let ctx_bound = super::traits::ctx_bound();
1544
1545 let ParsedGenerics { gen_use, .. } = all_generics;
1546
1547 for TraitInfo {
1548 path,
1549 raw_ident,
1550 generics:
1551 ParsedGenerics {
1552 life_use: tr_life_use,
1553 gen_use: tr_gen_use,
1554 ..
1555 },
1556 ..
1557 } in iter
1558 {
1559 if let Some((ext_path, tr_info)) = self.ext_traits.get(raw_ident) {
1560 let mut impls = TokenStream::new();
1561
1562 let ext_name = format_ident!("{}Ext", raw_ident);
1563
1564 let (funcs, _, (_, assoc_idents, _), _) = super::traits::parse_trait(
1565 tr_info,
1566 crate_path,
1567 false,
1568 super::traits::process_item,
1569 );
1570
1571 for a in &assoc_idents {
1572 impls.extend(
1573 quote!(type #a = <Self as #ext_name<#tr_life_use #tr_gen_use>>::#a;),
1574 );
1575 }
1576
1577 for func in &funcs {
1578 func.int_trait_impl(Some(ext_path), &ext_name, &mut impls);
1579 }
1580
1581 let gen = quote! {
1582 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #gen_use>
1583 #path #raw_ident <#tr_life_use #tr_gen_use> for #self_ident<'cglue_a, CGlueInst, CGlueCtx, #gen_use>
1584 where
1585 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #crate_path::trait_group::CGlueObjBase,
1586 Self: #ext_path #ext_name<#tr_life_use #tr_gen_use>
1587 {
1588 #impls
1589 }
1590 };
1591
1592 ret.extend(gen);
1593 }
1594 }
1595
1596 ret
1597 }
1598
1599 fn mandatory_vtbl_defs<'a>(&'a self, iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
1608 let mut ret = TokenStream::new();
1609
1610 let cont_name = &self.cont_name;
1611
1612 let all_gen_use = &self.generics.gen_use;
1613
1614 for TraitInfo {
1615 vtbl_name,
1616 path,
1617 vtbl_typename,
1618 generics: ParsedGenerics { gen_use, .. },
1619 assocs: ParsedGenerics {
1620 gen_use: assoc_use, ..
1621 },
1622 ..
1623 } in iter
1624 {
1625 ret.extend(
1626 quote!(#vtbl_name: &'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use>, ),
1627 );
1628 }
1629
1630 ret
1631 }
1632
1633 fn impl_traits<'a>(&'a self, traits: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
1639 let mut ret = TokenStream::new();
1640
1641 for (
1642 i,
1643 TraitInfo {
1644 path,
1645 raw_ident,
1646 generics:
1647 ParsedGenerics {
1648 life_use, gen_use, ..
1649 },
1650 ..
1651 },
1652 ) in traits.enumerate()
1653 {
1654 if i != 0 {
1655 ret.extend(quote!(+));
1656 }
1657
1658 let (hrtb, life_use) = if life_use.is_empty() {
1659 (quote!(), quote!())
1660 } else {
1661 (quote!(for<'cglue_c>), quote!('cglue_c,))
1662 };
1663
1664 ret.extend(quote!(#hrtb #path #raw_ident <#life_use #gen_use>));
1665 }
1666
1667 ret
1668 }
1669
1670 fn optional_vtbl_defs(&self, inst_ident: TokenStream, ctx_ident: TokenStream) -> TokenStream {
1674 let mut ret = TokenStream::new();
1675
1676 let cont_name = &self.cont_name;
1677
1678 let gen_all_use = &self.generics.gen_use;
1679
1680 for TraitInfo {
1681 vtbl_name,
1682 path,
1683 vtbl_typename,
1684 generics: ParsedGenerics { gen_use, .. },
1685 assocs: ParsedGenerics {
1686 gen_use: assoc_use, ..
1687 },
1688 ..
1689 } in &self.optional_vtbl
1690 {
1691 ret.extend(
1692 quote!(#vtbl_name: ::core::option::Option<&'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<#inst_ident, #ctx_ident, #gen_all_use>, #gen_use #assoc_use>>, ),
1693 );
1694 }
1695
1696 ret
1697 }
1698
1699 fn ret_tmp_defs<'a>(&'a self, iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
1700 let mut ret = TokenStream::new();
1701
1702 for TraitInfo {
1703 ret_tmp_name,
1704 path,
1705 ret_tmp_typename,
1706 generics: ParsedGenerics { gen_use, .. },
1707 assocs: ParsedGenerics {
1708 gen_use: assoc_use, ..
1709 },
1710 ..
1711 } in self.mandatory_vtbl.iter().chain(iter)
1712 {
1713 ret.extend(
1714 quote!(#ret_tmp_name: #path #ret_tmp_typename<CGlueCtx, #gen_use #assoc_use>, ),
1715 );
1716 }
1717
1718 ret
1719 }
1720
1721 fn mixed_opt_vtbl_defs<'a>(&'a self, iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
1731 let mut ret = TokenStream::new();
1732
1733 let mut iter = iter.peekable();
1734
1735 let cont_name = &self.cont_name;
1736
1737 let all_gen_use = &self.generics.gen_use;
1738
1739 for (
1740 TraitInfo {
1741 vtbl_name,
1742 path,
1743 vtbl_typename,
1744 generics: ParsedGenerics { gen_use, .. },
1745 assocs:
1746 ParsedGenerics {
1747 gen_use: assoc_use, ..
1748 },
1749 ..
1750 },
1751 mandatory,
1752 ) in self.optional_vtbl.iter().map(|v| {
1753 if iter.peek() == Some(&v) {
1754 iter.next();
1755 (v, true)
1756 } else {
1757 (v, false)
1758 }
1759 }) {
1760 let def = match mandatory {
1761 true => {
1762 quote!(#vtbl_name: &'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use>, )
1763 }
1764 false => {
1765 quote!(#vtbl_name: ::core::option::Option<&'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use>>, )
1766 }
1767 };
1768 ret.extend(def);
1769 }
1770
1771 ret
1772 }
1773
1774 fn get_container_impl(
1776 &self,
1777 name: &Ident,
1778 trg_path: &TokenStream,
1779 all_generics: &ParsedGenerics,
1780 ) -> TokenStream {
1781 let cont_name = &self.cont_name;
1782
1783 let ParsedGenerics {
1784 gen_declare,
1785 gen_use,
1786 gen_where_bounds,
1787 ..
1788 } = &all_generics;
1789
1790 let ctx_bound = super::traits::ctx_bound();
1791
1792 quote! {
1793 impl<CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #gen_declare>
1794 #trg_path::GetContainer for #name<'_, CGlueInst, CGlueCtx, #gen_use>
1795 where
1796 #cont_name<CGlueInst, CGlueCtx, #gen_use>: #trg_path::CGlueObjBase,
1797 #gen_where_bounds
1798 {
1799 type ContType = #cont_name<CGlueInst, CGlueCtx, #gen_use>;
1800
1801 fn ccont_ref(&self) -> &Self::ContType {
1802 &self.container
1803 }
1804
1805 fn ccont_mut(&mut self) -> &mut Self::ContType {
1806 &mut self.container
1807 }
1808
1809 fn into_ccont(self) -> Self::ContType {
1810 self.container
1811 }
1812
1813 fn build_with_ccont(&self, container: Self::ContType) -> Self {
1814 Self {
1815 container,
1816 ..*self
1817 }
1818 }
1819 }
1820 }
1821 }
1822
1823 fn cglue_obj_impl(&self, trg_path: &TokenStream, all_generics: &ParsedGenerics) -> TokenStream {
1824 let cont_name = &self.cont_name;
1825
1826 let ParsedGenerics {
1827 gen_declare: all_gen_declare,
1828 gen_use: all_gen_use,
1829 gen_where_bounds: all_gen_where_bounds,
1830 ..
1831 } = &all_generics;
1832
1833 let ctx_bound = super::traits::ctx_bound();
1834
1835 let mut ret = quote! {
1836 impl<CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #all_gen_declare> #trg_path::CGlueObjBase
1837 for #cont_name<CGlueInst, CGlueCtx, #all_gen_use>
1838 where
1839 CGlueInst::Target: Sized,
1840 #all_gen_where_bounds
1841 {
1842 type ObjType = CGlueInst::Target;
1843 type InstType = CGlueInst;
1844 type Context = CGlueCtx;
1845
1846 fn cobj_base_ref(&self) -> (&Self::ObjType, &Self::Context) {
1847 (self.instance.deref(), &self.context)
1848 }
1849
1850 fn cobj_base_owned(self) -> (Self::InstType, Self::Context) {
1851 (self.instance, self.context)
1852 }
1853 }
1854 };
1855
1856 for TraitInfo {
1857 path,
1858 ret_tmp_typename,
1859 ret_tmp_name,
1860 generics: ParsedGenerics { gen_use, .. },
1861 assocs: ParsedGenerics {
1862 gen_use: assoc_use, ..
1863 },
1864 ..
1865 } in self.mandatory_vtbl.iter().chain(self.optional_vtbl.iter())
1866 {
1867 ret.extend(quote!{
1868 impl<CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #all_gen_declare>
1869 #trg_path::CGlueObjRef<#path #ret_tmp_typename<CGlueCtx, #gen_use #assoc_use>>
1870 for #cont_name<CGlueInst, CGlueCtx, #all_gen_use>
1871 where
1872 CGlueInst::Target: Sized,
1873 #all_gen_where_bounds
1874 {
1875 fn cobj_ref(&self) -> (&Self::ObjType, &#path #ret_tmp_typename<CGlueCtx, #gen_use #assoc_use>, &Self::Context) {
1876 (self.instance.deref(), &self.#ret_tmp_name, &self.context)
1877 }
1878 }
1879
1880 impl<
1881 CGlueInst: ::core::ops::DerefMut,
1882 CGlueCtx: #ctx_bound,
1883 #all_gen_declare
1884 > #trg_path::CGlueObjMut<#path #ret_tmp_typename<CGlueCtx, #gen_use #assoc_use>>
1885 for #cont_name<CGlueInst, CGlueCtx, #all_gen_use>
1886 where
1887 CGlueInst::Target: Sized,
1888 #all_gen_where_bounds
1889 {
1890 fn cobj_mut(&mut self) -> (&mut Self::ObjType, &mut #path #ret_tmp_typename<CGlueCtx, #gen_use #assoc_use>, &Self::Context) {
1891 (
1892 self.instance.deref_mut(),
1893 &mut self.#ret_tmp_name,
1894 &self.context,
1895 )
1896 }
1897 }
1898 });
1899 }
1900
1901 ret
1902 }
1903
1904 fn mandatory_as_ref_impls(&self, trg_path: &TokenStream) -> TokenStream {
1906 self.as_ref_impls(
1907 &self.name,
1908 self.mandatory_vtbl.iter(),
1909 &self.generics,
1910 trg_path,
1911 )
1912 }
1913
1914 fn as_ref_impls<'a>(
1921 &'a self,
1922 name: &Ident,
1923 traits: impl Iterator<Item = &'a TraitInfo>,
1924 all_generics: &ParsedGenerics,
1925 trg_path: &TokenStream,
1926 ) -> TokenStream {
1927 let mut ret = TokenStream::new();
1928
1929 let cont_name = &self.cont_name;
1930
1931 let all_gen_declare = &all_generics.gen_declare;
1932 let all_gen_use = &all_generics.gen_use;
1933 let all_gen_where_bounds = &all_generics.gen_where_bounds;
1934
1935 let ctx_bound = super::traits::ctx_bound();
1936
1937 for TraitInfo {
1938 vtbl_name,
1939 path,
1940 vtbl_typename,
1941 vtbl_get_ident,
1942 assoc_bind_ident,
1943 generics: ParsedGenerics { gen_use, .. },
1944 assocs: ParsedGenerics {
1945 gen_use: assoc_use, ..
1946 },
1947 ..
1948 } in traits
1949 {
1950 ret.extend(quote! {
1951
1952 impl<'cglue_a, CGlueInst, CGlueCtx: #ctx_bound, #all_gen_declare> #trg_path::GetVtblBase<#path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use>>
1955 for #name<'cglue_a, CGlueInst, CGlueCtx, #all_gen_use>
1956 where
1957 #cont_name<CGlueInst, CGlueCtx, #all_gen_use>: #trg_path::CGlueObjBase,
1958 #all_gen_where_bounds
1959 {
1960 fn get_vtbl_base(&self) -> &#path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use> {
1961 &self.#vtbl_name
1962 }
1963 }
1964
1965 impl<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #all_gen_declare> #path #vtbl_get_ident<'cglue_a, #gen_use #assoc_use>
1966 for #name<'cglue_a, CGlueInst, CGlueCtx, #all_gen_use>
1967 where
1968 <CGlueInst as ::core::ops::Deref>::Target: Sized,
1969 #cont_name<CGlueInst, CGlueCtx, #all_gen_use>: #trg_path::CGlueObjBase,
1970 #all_gen_where_bounds
1971 {
1972 fn get_vtbl(&self) -> &#path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #all_gen_use>, #gen_use #assoc_use> {
1973 &self.#vtbl_name
1974 }
1975 }
1976
1977 impl<'cglue_a, CGlueInst: ::core::ops::Deref, CGlueCtx: #ctx_bound, #all_gen_declare> #path #assoc_bind_ident<#gen_use>
1978 for #name<'cglue_a, CGlueInst, CGlueCtx, #all_gen_use>
1979 where
1980 <CGlueInst as ::core::ops::Deref>::Target: Sized,
1981 #cont_name<CGlueInst, CGlueCtx, #all_gen_use>: #trg_path::CGlueObjBase,
1982 #all_gen_where_bounds
1983 {
1984 type Assocs = (#assoc_use);
1985 }
1986 });
1987 }
1988
1989 ret
1990 }
1991
1992 fn mandatory_vtbl_defaults(&self) -> TokenStream {
1994 let mut ret = TokenStream::new();
1995
1996 for TraitInfo { vtbl_name, .. } in &self.mandatory_vtbl {
1997 ret.extend(quote!(#vtbl_name: Default::default(),));
1998 }
1999
2000 ret
2001 }
2002
2003 fn mandatory_ret_tmp_defaults(&self) -> TokenStream {
2004 Self::ret_tmp_defaults(self.mandatory_vtbl.iter())
2005 }
2006
2007 fn ret_tmp_defaults<'a>(iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
2008 let mut ret = TokenStream::new();
2009
2010 for TraitInfo { ret_tmp_name, .. } in iter {
2011 ret.extend(quote!(#ret_tmp_name: Default::default(),));
2012 }
2013
2014 ret
2015 }
2016
2017 #[cfg_attr(not(feature = "unstable"), allow(unused))]
2019 fn default_opt_vtbl_list(&self) -> TokenStream {
2020 let mut ret = TokenStream::new();
2021
2022 #[cfg(feature = "unstable")]
2023 let crate_path = crate::util::crate_path();
2024
2025 let cont_name = &self.cont_name;
2026
2027 let gen_all_use = &self.generics.gen_use;
2028
2029 for TraitInfo {
2030 vtbl_name,
2031 path,
2032 vtbl_typename,
2033 generics: ParsedGenerics { gen_use, .. },
2034 assocs: ParsedGenerics {
2035 gen_use: assoc_use, ..
2036 },
2037 ..
2038 } in &self.optional_vtbl
2039 {
2040 #[cfg(feature = "unstable")]
2041 {
2042 let vtbl_ty = quote!(&'cglue_a #path #vtbl_typename<'cglue_a, #cont_name<CGlueInst, CGlueCtx, #gen_all_use>, #gen_use #assoc_use>);
2043 ret.extend(quote!(#vtbl_name: <#vtbl_ty as #crate_path::TryDefault<#vtbl_ty>>::try_default(),));
2044 }
2045 #[cfg(not(feature = "unstable"))]
2046 ret.extend(quote!(#vtbl_name: None,));
2047 }
2048
2049 ret
2050 }
2051
2052 fn vtbl_list<'a>(&'a self, iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
2054 let mut ret = TokenStream::new();
2055
2056 for TraitInfo { vtbl_name, .. } in iter {
2057 ret.extend(quote!(#vtbl_name,));
2058 }
2059
2060 ret
2061 }
2062
2063 fn vtbl_unwrap_list<'a>(&'a self, iter: impl Iterator<Item = &'a TraitInfo>) -> TokenStream {
2069 let mut ret = TokenStream::new();
2070
2071 for TraitInfo { vtbl_name, .. } in iter {
2072 ret.extend(quote!(#vtbl_name: #vtbl_name?,));
2073 }
2074
2075 ret
2076 }
2077
2078 fn mixed_opt_vtbl_unwrap_list<'a>(
2087 &'a self,
2088 iter: impl Iterator<Item = &'a TraitInfo>,
2089 ) -> TokenStream {
2090 let mut ret = TokenStream::new();
2091
2092 let mut iter = iter.peekable();
2093
2094 for (TraitInfo { vtbl_name, .. }, mandatory) in self.optional_vtbl.iter().map(|v| {
2095 if iter.peek() == Some(&v) {
2096 iter.next();
2097 (v, true)
2098 } else {
2099 (v, false)
2100 }
2101 }) {
2102 let def = match mandatory {
2103 true => quote!(#vtbl_name: #vtbl_name?, ),
2104 false => quote!(#vtbl_name, ),
2105 };
2106 ret.extend(def);
2107 }
2108
2109 ret
2110 }
2111
2112 fn vtbl_unwrap_validate<'a>(
2118 &'a self,
2119 iter: impl Iterator<Item = &'a TraitInfo>,
2120 ) -> TokenStream {
2121 let mut ret = TokenStream::new();
2122
2123 for TraitInfo { vtbl_name, .. } in iter {
2124 ret.extend(quote!((*#vtbl_name)?,));
2125 }
2126
2127 ret
2128 }
2129
2130 pub fn vtbl_where_bounds<'a>(
2132 iter: impl Iterator<Item = &'a TraitInfo>,
2133 cont_name: &Ident,
2134 container_ident: TokenStream,
2135 ctx_ident: TokenStream,
2136 all_generics: &ParsedGenerics,
2137 trait_bound: Option<&TokenStream>,
2138 vtbl_lifetime: &Lifetime,
2139 ) -> TokenStream {
2140 let mut ret = TokenStream::new();
2141
2142 let all_gen_use = &all_generics.gen_use;
2143
2144 for TraitInfo {
2145 path,
2146 raw_ident,
2147 vtbl_typename,
2148 generics: ParsedGenerics {
2149 gen_use, life_use, ..
2150 },
2151 assocs: ParsedGenerics {
2152 gen_use: assoc_use, ..
2153 },
2154 ..
2155 } in iter
2156 {
2157 if let Some(trait_bound) = &trait_bound {
2160 let life_use = if life_use.is_empty() {
2162 None
2163 } else {
2164 Some(quote!('cglue_a,))
2165 };
2166
2167 ret.extend(quote!(#trait_bound: #path #raw_ident<#life_use #gen_use>,));
2168 }
2169
2170 ret.extend(quote!(&#vtbl_lifetime #path #vtbl_typename<#vtbl_lifetime, #cont_name<#container_ident, #ctx_ident, #all_gen_use>, #gen_use #assoc_use>: #vtbl_lifetime + Default,));
2171 }
2172
2173 ret
2174 }
2175}