cglue_gen/
trait_groups.rs

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
47/// Describes information about a single trait.
48pub 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/// Describes parse trait group, allows to generate code for it.
135#[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        // TODO: parse associated type defs here
153        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        // Go through mand/opt vtbls and pick all external traits used out of there,
193        // and then pick add those trait definitions to the ext_traits list from both
194        // the input list, and the standard trait collection.
195        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 the user has supplied a custom implementation.
206            if let Some(tr) = ext_trait_defs.iter().find(|tr| tr.ident == vtbl.raw_ident) {
207                // Keep the leading colon so as to allow going from the root or relatively
208                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                // Check the store otherwise
233                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                    // If we are in the store, we should push crate_path path to the very start
244                    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/// Describes trait group to be implemented on a type.
287#[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        // Parse generic arguments from the type.
304        // Here we assume the last instance of AngleBracketed are generic arguments.
305        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    /// Generate trait group conversion for a specific type.
384    ///
385    /// The type will have specified vtables implemented as a conversion function.
386    #[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 no lifetimes are used, default to 'cglue_a
415        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        // Lifetime should always exist based on previous code
439        let first_life = life_use.first().unwrap();
440
441        let gen_lt_bounds = self.generics.declare_lt_for_all(&quote!(#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    /// Generate a cast to a specific type.
557    ///
558    /// The type will have specified vtables implemented as a conversion function.
559    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    /// Identifier for optional group struct.
579    ///
580    /// # Arguments
581    ///
582    /// * `name` - base name of the trait group.
583    /// * `postfix` - postfix to add after the naem, and before `With`.
584    /// * `traits` - traits that are to be implemented.
585    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    /// Get the name of the function for trait conversion.
600    ///
601    /// # Arguments
602    ///
603    /// * `prefix` - function name prefix.
604    /// * `lc_names` - lowercase identifiers of the traits the function implements.
605    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    /// Generate function calls that enable individual functional vtables.
619    ///
620    /// # Arguments
621    ///
622    /// * `iter` - iterator of optional traits to enable
623    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    /// Generate full code for the trait group.
637    ///
638    /// This trait group will have all variants generated for converting, building, and
639    /// converting it.
640    pub fn create_group(&self) -> TokenStream {
641        // Path to trait group import.
642        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(&quote!('cglue_a));
661        let gen_sabi_bounds = self.generics.declare_sabi_for_all(&crate_path);
662
663        // Structures themselves do not need StableAbi bounds, if layout_checks is on
664        let gen_where_bounds_base = quote! {
665            #gen_where_bounds
666            #gen_lt_bounds
667        };
668
669        // If layout_checks is enabled, this will include StableAbi bounds
670        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        // Work around needless_update lint
752        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, &quote!(..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            // TODO: remove unused generics to remove need for phantom data
900
901            opt_struct_imports.extend(quote! {
902                #opt_final_name,
903                #opt_name,
904            });
905
906            opt_structs.extend(quote! {
907
908                // Final implementation - more compact layout.
909
910                #[doc = #opt_final_doc]
911                ///
912                #[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                // Non-final implementation. Has the same layout as the base struct.
932
933                #[doc = #opt_doc]
934                ///
935                #[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                    /// Cast back into the original group
974                    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                ///
1018                #[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                ///
1027                #[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                ///
1047                #[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                    // Safety:
1078                    //
1079                    // Structure layouts are fully compatible,
1080                    // optional reference validity was checked beforehand
1081
1082                    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                    // Safety:
1100                    //
1101                    // Structure layouts are fully compatible,
1102                    // optional reference validity was checked beforehand
1103
1104                    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                ///
1219                /// Optional traits are not implemented here, however. There are numerous conversion
1220                /// functions available for safely retrieving a concrete collection of traits.
1221                ///
1222                /// `check_impl_` functions allow to check if the object implements the wanted traits.
1223                ///
1224                /// `into_impl_` functions consume the object and produce a new final structure that
1225                /// keeps only the required information.
1226                ///
1227                /// `cast_impl_` functions merely check and transform the object into a type that can
1228                #[doc = #trback_doc]
1229                ///
1230                /// `as_ref_`, and `as_mut_` functions obtain references to safe objects, but do not
1231                /// perform any memory transformations either. They are the safest to use, because
1232                /// there is no risk of accidentally consuming the whole object.
1233                #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                    ///
1487                    /// `instance` will be moved onto heap.
1488                    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                /// Convert into opaque object.
1496                ///
1497                /// This is the prerequisite for using underlying trait implementations.
1498                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, //: ::core::ops::Deref
1511                    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    /// Required vtable definitions.
1600    ///
1601    /// Required means they must be valid - non-Option.
1602    ///
1603    /// # Arguments
1604    ///
1605    /// * `iter` - can be any list of traits.
1606    ///
1607    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    /// Get a sequence of `Trait1 + Trait2 + Trait3 ...`
1634    ///
1635    /// # Arguments
1636    ///
1637    /// * `traits` - traits to combine.
1638    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    /// Optional and vtable definitions.
1671    ///
1672    /// Optional means they are of type `Option<&'cglue_a VTable>`.
1673    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    /// Mixed vtable definitoins.
1722    ///
1723    /// This function goes through optional vtables, and mixes them between `Option`, and
1724    /// non-`Option` types for the definitions.
1725    ///
1726    /// # Arguments
1727    ///
1728    /// * `iter` - iterator of required/mandatory types. These types will have non-`Option` type
1729    /// assigned. It is crucial to have the same order of values!
1730    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    /// Generate a `GetContainer` implementation for a specific cglue object.
1775    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    /// `GetVtbl<Vtable>`, `CGlueObjRef<RetTmp>`, `CGlueObjOwned<RetTmp>`, `CGlueObjBuild<RetTmp>`, and `CGlueObjMut<T, RetTmp>` implementations for mandatory vtables.
1905    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    /// `GetVtbl<Vtable>`, `CGlueObjRef<RetTmp>`, `CGlueObjOwned<RetTmp>`, `CGlueObjBuild<RetTmp>`, and `CGlueObjMut<T, RetTmp>` implementations for arbitrary type and list of tables.
1915    ///
1916    /// # Arguments
1917    ///
1918    /// * `name` - type name to implement the conversion for.
1919    /// * `traits` - vtable types to implement the conversion to.
1920    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                // TODO: bring back CGlueObjBuild
1953
1954                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    /// List of `vtbl: Default::default(), ` for all mandatory vtables.
1993    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    /// List of `vtbl: None, ` for all optional vtables.
2018    #[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    /// Simple identifier list.
2053    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    /// Try-unwrapping assignment list `vtbl: vtbl?, `.
2064    ///
2065    /// # Arguments
2066    ///
2067    /// * `iter` - vtable identifiers to list and try-unwrap.
2068    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    /// Mixed try-unwrap list for vtables.
2079    ///
2080    /// This function goes through optional vtables, unwraps the ones in `iter`, leaves others
2081    /// bare.
2082    ///
2083    /// # Arguments
2084    ///
2085    /// * `iter` - list of vtables to try-unwrap. Must be ordered the same way!
2086    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    /// Try-unwrap a list of vtables without assigning them (`vtbl?,`).
2113    ///
2114    /// # Arguments
2115    ///
2116    /// * `iter` - vtables to unwrap.
2117    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    /// Bind `Default` to mandatory vtables.
2131    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            // FIXME: this is a bit of a hack. 0.1 could do multiple generic implementations
2158            // without trait bounds just fine.
2159            if let Some(trait_bound) = &trait_bound {
2160                // FIXME: this will not work with multiple lifetimes.
2161                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}