cglue_gen/
traits.rs

1use proc_macro2::TokenStream;
2
3use std::collections::BTreeMap;
4
5use super::func::{AssocType, CustomFuncImpl, ParsedFunc, WrappedType};
6use super::generics::{GenericType, ParsedGenerics};
7
8use quote::*;
9use syn::{
10    parse::*,
11    punctuated::Punctuated,
12    token::{Add, Comma},
13    *,
14};
15
16pub struct PathTokens {
17    lifetime: Option<Lifetime>,
18    path: Path,
19    tokens: TokenStream,
20}
21
22impl Parse for PathTokens {
23    fn parse(input: ParseStream) -> Result<Self> {
24        let lifetime = if let Ok(lifetime) = input.parse() {
25            input.parse::<Comma>()?;
26            Some(lifetime)
27        } else {
28            None
29        };
30
31        let path = input.parse()?;
32        let tokens = input.parse()?;
33
34        Ok(Self {
35            lifetime,
36            path,
37            tokens,
38        })
39    }
40}
41
42// TODO: Add dynamic setting of Send / Sync
43pub fn ctx_bound() -> TokenStream {
44    let crate_path = crate::util::crate_path();
45    quote!(#crate_path::trait_group::ContextBounds)
46}
47
48pub fn cglue_c_opaque_bound() -> TokenStream {
49    let crate_path = crate::util::crate_path();
50    quote!(CGlueC::OpaqueTarget: #crate_path::trait_group::Opaquable + #crate_path::trait_group::CGlueObjBase,)
51}
52
53pub fn process_item(
54    (ty_def, ty_bounds, ty_where_clause, ty_attrs): (
55        &Option<AssocType>,
56        &Punctuated<TypeParamBound, Add>,
57        Option<&WhereClause>,
58        &[Attribute],
59    ),
60    trait_name: &Ident,
61    generics: &ParsedGenerics,
62    trait_type_defs: &mut TokenStream,
63    types: &mut BTreeMap<Option<AssocType>, WrappedType>,
64    assoc_types: &mut BTreeMap<AssocType, Punctuated<TypeParamBound, Add>>,
65    crate_path: &TokenStream,
66) {
67    let c_void = crate::util::void_type();
68
69    let static_lifetime = Lifetime {
70        apostrophe: proc_macro2::Span::call_site(),
71        ident: format_ident!("static"),
72    };
73
74    let cglue_a_lifetime = Lifetime {
75        apostrophe: proc_macro2::Span::call_site(),
76        ident: format_ident!("cglue_a"),
77    };
78
79    let cglue_b_lifetime = Lifetime {
80        apostrophe: proc_macro2::Span::call_site(),
81        ident: format_ident!("cglue_b"),
82    };
83
84    let cglue_c_lifetime = Lifetime {
85        apostrophe: proc_macro2::Span::call_site(),
86        ident: format_ident!("cglue_c"),
87    };
88
89    let mut lifetime_bounds = ty_bounds.iter().filter_map(|b| match b {
90        TypeParamBound::Lifetime(lt) => Some(lt),
91        _ => None,
92    });
93
94    let orig_lifetime_bound = lifetime_bounds.next();
95
96    // When anonymous lifetime is passed, use self lifetime
97    let orig_lifetime_bound = if orig_lifetime_bound.map(|lt| lt.ident == "_") == Some(true) {
98        Some(&cglue_c_lifetime)
99    } else {
100        orig_lifetime_bound
101    };
102
103    if lifetime_bounds.next().is_some() {
104        panic!("Traits with multiple lifetime bounds are not supported!");
105    }
106
107    let mut wrapped = false;
108
109    for attr in ty_attrs {
110        let s = attr.path.to_token_stream().to_string();
111
112        let x = s.as_str();
113
114        match x {
115            "wrap_with" => {
116                wrapped = true;
117                let new_ty = attr
118                    .parse_args::<GenericType>()
119                    .expect("Invalid type in wrap_with.");
120
121                if let Some(ty_def) = ty_def {
122                    trait_type_defs.extend(quote!(type #ty_def = #new_ty #ty_where_clause;));
123                }
124
125                types.insert(
126                    ty_def.clone(),
127                    WrappedType {
128                        ty: new_ty.clone(),
129                        ty_ret_tmp: Some(new_ty),
130                        ty_static: None,
131                        return_conv: None,
132                        lifetime_bound: None,
133                        lifetime_type_bound: None,
134                        other_bounds: None,
135                        other_bounds_simple: None,
136                        impl_return_conv: None,
137                        inject_ret_tmp: false,
138                        unbounded_hrtb: false,
139                    },
140                );
141            }
142            "return_wrap" => {
143                wrapped = true;
144                let closure = attr
145                    .parse_args::<ExprClosure>()
146                    .expect("A valid closure must be supplied accepting the wrapped type!");
147
148                types
149                    .get_mut(ty_def)
150                    .expect("Type must be first wrapped with #[wrap_with(T)] atribute.")
151                    .return_conv = Some(closure);
152            }
153            "wrap_with_obj"
154            | "wrap_with_obj_ref"
155            | "wrap_with_obj_mut"
156            | "wrap_with_group"
157            | "wrap_with_group_ref"
158            | "wrap_with_group_mut" => {
159                wrapped = true;
160                let mut new_ty = attr
161                    .parse_args::<GenericType>()
162                    .expect("Invalid type in wrap_with.");
163
164                let target_ty = new_ty.clone();
165                let target = new_ty.target.clone();
166
167                //if target.to_string() == "G"
168
169                if ["wrap_with_obj", "wrap_with_obj_ref", "wrap_with_obj_mut"].contains(&x) {
170                    new_ty.target = format_ident!("{}Base", target.to_string()).to_token_stream();
171                }
172
173                // These variables model a `CGlueF::#ty_def: Into<SomeGroup>` bound.
174                let mut from_new_ty = new_ty.clone();
175                let mut from_new_ty_ref = TokenStream::new();
176                let mut from_new_ty_simple = new_ty.clone();
177                let mut from_new_ty_simple_ref = TokenStream::new();
178
179                let mut new_ty_static = new_ty.clone();
180
181                // Inject static bound when we wrap owned objects, because we can not ensure their
182                // safety like that.
183                let lifetime_bound = if orig_lifetime_bound.is_none()
184                    && (x == "wrap_with_group" || x == "wrap_with_obj")
185                {
186                    Some(&static_lifetime)
187                } else {
188                    orig_lifetime_bound
189                };
190
191                let lifetime = lifetime_bound.unwrap_or(&static_lifetime);
192
193                // Insert the object lifetime at the start
194                new_ty.push_lifetime_start(lifetime);
195                new_ty_static.push_lifetime_start(&static_lifetime);
196
197                let from_lifetime = if (x == "wrap_with_group" || x == "wrap_with_obj")
198                    && lifetime == &static_lifetime
199                {
200                    lifetime
201                } else {
202                    &cglue_b_lifetime
203                };
204
205                from_new_ty.push_lifetime_start(from_lifetime);
206
207                let from_lifetime_simple = if (x == "wrap_with_group" || x == "wrap_with_obj")
208                    && lifetime == &static_lifetime
209                {
210                    lifetime
211                } else {
212                    &cglue_a_lifetime
213                };
214
215                from_new_ty_simple.push_lifetime_start(from_lifetime_simple);
216
217                let gen_use = &generics.gen_use;
218
219                let mut new_ty_trait_impl = new_ty.clone();
220                let mut new_ty_ret_tmp = new_ty.clone();
221
222                let (other_bounds, other_bounds_simple) = {
223                    let (type_bounds, type_bounds_simple) = {
224                        // Here we must inject a lifetime, if the trait has no lifetime,
225                        // and its a group we are wrapping
226                        let hrtb_lifetime = quote!(#cglue_b_lifetime);
227
228                        let hrtb_lifetime_use = if generics.life_use.is_empty() {
229                            quote!()
230                        } else {
231                            quote!(#from_lifetime)
232                        };
233
234                        let simple_lifetime_use = if generics.life_use.is_empty() {
235                            quote!()
236                        } else {
237                            quote!(#from_lifetime_simple)
238                        };
239
240                        let cglue_f_tys = ty_def.as_ref().map(|ty_def| {
241                            let ty_def = ty_def.remap_for_hrtb();
242                            (
243                                quote!(<CGlueC::ObjType as #trait_name<#hrtb_lifetime_use #gen_use>>::#ty_def),
244                                quote!(<CGlueC::ObjType as #trait_name<#simple_lifetime_use #gen_use>>::#ty_def),
245                            )
246                        });
247
248                        let mut new_ty_hrtb = from_new_ty.clone();
249                        let mut new_ty_simple = from_new_ty_simple.clone();
250
251                        if x == "wrap_with_group" || x == "wrap_with_obj" {
252                            // <CGlueO::ContType as crate::trait_group::CGlueObjBase>::Context
253                            new_ty.push_types_start(
254                                quote!(#crate_path::boxed::CBox<#lifetime, #c_void>, CGlueC::Context, ),
255                            );
256                            new_ty_ret_tmp.push_types_start(
257                                quote!(#crate_path::boxed::CBox<#lifetime, #c_void>, CGlueCtx, ),
258                            );
259                            new_ty_trait_impl.push_types_start(
260                                quote!(#crate_path::boxed::CBox<#lifetime, #c_void>, <CGlueO::ContType as #crate_path::trait_group::CGlueObjBase>::Context, ),
261                            );
262                            new_ty_hrtb.push_types_start(
263                                quote!(#crate_path::boxed::CBox<#from_lifetime, #c_void>, CGlueC::Context, ),
264                            );
265                            new_ty_simple.push_types_start(
266                                quote!(#crate_path::boxed::CBox<#from_lifetime_simple, #c_void>, CGlueC::Context, ),
267                            );
268                            new_ty_static.push_types_start(
269                                quote!(#crate_path::boxed::CBox<'static, #c_void>, CGlueCtx, ),
270                            );
271
272                            if let Some((cglue_f_ty_def, cglue_f_ty_simple_ident)) = &cglue_f_tys {
273                                from_new_ty.push_types_start(
274                                    quote!(#crate_path::boxed::CBox<#from_lifetime, #cglue_f_ty_def>, CGlueC::Context, ),
275                                );
276                                from_new_ty_simple.push_types_start(
277                                    quote!(#crate_path::boxed::CBox<#from_lifetime_simple, #cglue_f_ty_simple_ident>, CGlueC::Context, ),
278                                );
279                            }
280                        } else if x == "wrap_with_group_ref" || x == "wrap_with_obj_ref" {
281                            let no_context = quote!(CGlueC::Context);
282                            new_ty.push_types_start(quote!(&#lifetime #c_void, CGlueC::Context, ));
283                            new_ty_ret_tmp.push_types_start(quote!(&#lifetime #c_void, CGlueCtx, ));
284                            new_ty_trait_impl.push_types_start(
285                                quote!(&#lifetime #c_void, <CGlueO::ContType as crate::trait_group::CGlueObjBase>::Context, ),
286                            );
287                            new_ty_hrtb.push_types_start(
288                                quote!(&#from_lifetime #c_void, CGlueC::Context, ),
289                            );
290                            new_ty_simple.push_types_start(
291                                quote!(&#from_lifetime_simple #c_void, CGlueC::Context, ),
292                            );
293                            new_ty_static.push_types_start(quote!(&'static #c_void, CGlueCtx, ));
294                            if let Some((cglue_f_ty_def, cglue_f_ty_simple_ident)) = &cglue_f_tys {
295                                from_new_ty.push_types_start(
296                                    quote!(&#from_lifetime #cglue_f_ty_def, #no_context, ),
297                                );
298                                from_new_ty_ref.extend(quote!(&#from_lifetime));
299                                from_new_ty_simple.push_types_start(
300                                    quote!(&#from_lifetime_simple #cglue_f_ty_simple_ident, #no_context, ),
301                                );
302                                from_new_ty_simple_ref.extend(quote!(&#from_lifetime_simple));
303                            }
304                        } else if x == "wrap_with_group_mut" || x == "wrap_with_obj_mut" {
305                            let no_context = quote!(CGlueC::Context);
306                            new_ty.push_types_start(
307                                quote!(&#lifetime mut #c_void, CGlueC::Context, ),
308                            );
309                            new_ty_ret_tmp
310                                .push_types_start(quote!(&#lifetime mut #c_void, CGlueCtx, ));
311                            new_ty_trait_impl.push_types_start(
312                                quote!(&#lifetime mut #c_void, <CGlueO::ContType as crate::trait_group::CGlueObjBase>::Context, ),
313                            );
314                            new_ty_hrtb.push_types_start(
315                                quote!(&#from_lifetime mut #c_void, CGlueC::Context, ),
316                            );
317                            new_ty_simple.push_types_start(
318                                quote!(&#from_lifetime_simple mut #c_void, CGlueC::Context, ),
319                            );
320                            new_ty_static
321                                .push_types_start(quote!(&'static mut #c_void, CGlueCtx, ));
322                            if let Some((cglue_f_ty_def, cglue_f_ty_simple_ident)) = &cglue_f_tys {
323                                from_new_ty.push_types_start(
324                                    quote!(&#from_lifetime mut #cglue_f_ty_def, #no_context, ),
325                                );
326                                from_new_ty_ref.extend(quote!(&#from_lifetime mut));
327                                from_new_ty_simple.push_types_start(
328                                    quote!(&#from_lifetime_simple mut #cglue_f_ty_simple_ident, #no_context, ),
329                                );
330                                from_new_ty_simple_ref.extend(quote!(&#from_lifetime_simple mut));
331                            }
332                        } else {
333                            unreachable!()
334                        }
335
336                        if let Some((cglue_f_ty_def, cglue_f_ty_simple_ident)) = cglue_f_tys {
337                            let (ty_ref, ty_ref_simple) = {
338                                (
339                                    quote!((#from_new_ty_ref #cglue_f_ty_def, CGlueC::Context)),
340                                    quote!((#from_new_ty_simple_ref #cglue_f_ty_simple_ident, CGlueC::Context)),
341                                )
342                            };
343
344                            let type_bounds = quote! {
345                                for<#hrtb_lifetime> #ty_ref: Into<#from_new_ty>,
346                                for<#hrtb_lifetime> #from_new_ty: #crate_path::trait_group::Opaquable<OpaqueTarget = #new_ty_hrtb>,
347                            };
348
349                            let type_bounds_simple = quote! {
350                                #ty_ref_simple: Into<#from_new_ty_simple>,
351                                #from_new_ty_simple: #crate_path::trait_group::Opaquable<OpaqueTarget = #new_ty_simple>,
352                            };
353                            (Some(type_bounds), Some(type_bounds_simple))
354                        } else if lifetime_bound == Some(&static_lifetime) {
355                            (
356                                Some(quote!(CGlueC::ObjType: 'static,)),
357                                Some(quote!(CGlueC::ObjType: 'static,)),
358                            )
359                        } else {
360                            (None, None)
361                        }
362                    };
363
364                    if let Some(ty_def) = ty_def {
365                        trait_type_defs
366                            .extend(quote!(type #ty_def = #new_ty_trait_impl #ty_where_clause;));
367                    }
368
369                    (type_bounds, type_bounds_simple)
370                };
371
372                let ret_write_unsafe = quote! {
373                    // SAFETY:
374                    // We cast anon lifetime to static lifetime. It is rather okay, because we are only
375                    // returning reference to the object.
376                    unsafe {
377                        // Transmute sometimes does not work even when same size CGlueTraitObj is used, and
378                        // only lifetimes differ. Manually assert sizes, which will result in either a no-op
379                        // or forced panic on release builds.
380                        assert!(std::mem::size_of_val(ret_tmp) == std::mem::size_of_val(&ret));
381                        std::ptr::copy_nonoverlapping(std::mem::transmute(&ret), ret_tmp.as_mut_ptr(), 1);
382                        std::mem::forget(ret);
383                    }
384                };
385
386                let (ret_write, conv_bound) = if lifetime != &static_lifetime {
387                    (
388                        quote! {
389                            unsafe {
390                                ret_tmp.as_mut_ptr().write(ret);
391                            }
392                        },
393                        quote!(#lifetime),
394                    )
395                } else {
396                    (ret_write_unsafe.clone(), quote!('cglue_a))
397                };
398
399                let target = target_ty;
400
401                let (return_conv, inject_ret_tmp) = match x {
402                    "wrap_with_obj" => (
403                        parse2(quote!(|ret| trait_obj!((ret, cglue_ctx) as #target)))
404                            .expect("Internal closure parsing fail"),
405                        false,
406                    ),
407                    "wrap_with_group" => (
408                        parse2(quote!(|ret| group_obj!((ret, cglue_ctx) as #target)))
409                            .expect("Internal closure parsing fail"),
410                        false,
411                    ),
412                    "wrap_with_obj_ref" => (
413                        parse2(quote!(|ret: &#conv_bound _| {
414                            let ret = trait_obj!((ret, cglue_ctx) as #target);
415                            #ret_write_unsafe
416                            unsafe { &*ret_tmp.as_ptr() }
417                        }))
418                        .expect("Internal closure parsing fail"),
419                        true,
420                    ),
421                    "wrap_with_group_ref" => (
422                        parse2(quote!(|ret: &#conv_bound _| {
423                            let ret = group_obj!((ret, cglue_ctx) as #target);
424                            #ret_write_unsafe
425                            unsafe { &*ret_tmp.as_ptr() }
426                        }))
427                        .expect("Internal closure parsing fail"),
428                        true,
429                    ),
430                    "wrap_with_obj_mut" => (
431                        parse2(quote!(|ret: &#conv_bound mut _| {
432                            let ret = trait_obj!((ret, cglue_ctx) as #target);
433                            #ret_write
434                            unsafe { &mut *ret_tmp.as_mut_ptr() }
435                        }))
436                        .expect("Internal closure parsing fail"),
437                        true,
438                    ),
439                    "wrap_with_group_mut" => (
440                        parse2(quote!(|ret: &#conv_bound mut _| {
441                            let ret = group_obj!((ret, cglue_ctx) as #target);
442                            #ret_write
443                            unsafe { &mut *ret_tmp.as_mut_ptr() }
444                        }))
445                        .expect("Internal closure parsing fail"),
446                        true,
447                    ),
448                    _ => unreachable!(),
449                };
450
451                // A very odd hack.
452                //
453                // On 1.45 compiling sometimes fails when the trait type is already bound for
454                // static, but an additional (redundant) static bound is added on top.
455                let lifetime_type_bound = if orig_lifetime_bound != Some(&static_lifetime) {
456                    lifetime_bound.cloned()
457                } else {
458                    None
459                };
460
461                let lifetime_bound = if lifetime_bound != Some(&static_lifetime) {
462                    lifetime_bound.cloned()
463                } else {
464                    None
465                };
466
467                //let lifetime_type_bound = lifetime_bound.clone();
468
469                types.insert(
470                    ty_def.clone(),
471                    WrappedType {
472                        ty: new_ty,
473                        ty_ret_tmp: Some(new_ty_ret_tmp),
474                        ty_static: Some(new_ty_static),
475                        return_conv: Some(return_conv),
476                        impl_return_conv: None,
477                        lifetime_bound,
478                        lifetime_type_bound,
479                        other_bounds,
480                        other_bounds_simple,
481                        inject_ret_tmp,
482                        unbounded_hrtb: false,
483                    },
484                );
485            }
486            _ => {}
487        }
488    }
489
490    if let (Some(ty_def), false) = (ty_def, wrapped) {
491        let new_ty = parse2(format_ident!("CGlueA{}", ty_def.ident).to_token_stream())
492            .expect("Invalid type in unwrapped assoc");
493
494        trait_type_defs.extend(quote!(type #ty_def = #new_ty #ty_where_clause;));
495
496        types.insert(
497            Some(ty_def.clone()),
498            WrappedType {
499                ty: new_ty,
500                ty_ret_tmp: None,
501                ty_static: None,
502                return_conv: None,
503                impl_return_conv: None,
504                lifetime_bound: None,
505                lifetime_type_bound: None,
506                other_bounds: None,
507                other_bounds_simple: None,
508                inject_ret_tmp: false,
509                unbounded_hrtb: false,
510            },
511        );
512
513        assoc_types.insert(ty_def.clone(), ty_bounds.clone());
514    }
515}
516
517pub fn parse_trait(
518    tr: &ItemTrait,
519    crate_path: &TokenStream,
520    also_parse_vtbl_only: bool,
521    mut process_item: impl FnMut(
522        (
523            &Option<AssocType>,
524            &Punctuated<TypeParamBound, Add>,
525            Option<&WhereClause>,
526            &[Attribute],
527        ),
528        &Ident,
529        &ParsedGenerics,
530        &mut TokenStream,
531        &mut BTreeMap<Option<AssocType>, WrappedType>,
532        &mut BTreeMap<AssocType, Punctuated<TypeParamBound, Add>>,
533        &TokenStream,
534    ),
535) -> (
536    Vec<ParsedFunc>,
537    ParsedGenerics,
538    (ParsedGenerics, Vec<Ident>, TokenStream),
539    TokenStream,
540) {
541    let mut funcs = vec![];
542    let generics = ParsedGenerics::from(&tr.generics);
543    let mut trait_type_defs = TokenStream::new();
544    let mut types = BTreeMap::new();
545    let mut types_c_side_vtbl = BTreeMap::new();
546
547    let mut assocs = BTreeMap::new();
548
549    let trait_name = &tr.ident;
550
551    types.insert(
552        Some(AssocType::from(format_ident!("Self"))),
553        WrappedType {
554            ty: parse2(quote!(CGlueC)).unwrap(),
555            // TODO: should we forward ty in here??
556            ty_ret_tmp: None,
557            ty_static: None,
558            return_conv: Some(
559                parse2(quote!(|ret| {
560                    use #crate_path::from2::From2;
561                    CGlueC::from2((ret, cglue_ctx))
562                }))
563                .expect("Internal closure parsing fail"),
564            ),
565            lifetime_bound: None,
566            lifetime_type_bound: None,
567            other_bounds: Some(quote!((CGlueC::ObjType, CGlueCtx): Into<CGlueC>,)),
568            other_bounds_simple: Some(quote!((CGlueC::ObjType, CGlueCtx): Into<CGlueC>,)),
569            impl_return_conv: Some(quote!(self.build_with_ccont(ret))),
570            inject_ret_tmp: false,
571            unbounded_hrtb: true,
572        },
573    );
574
575    let int_result = tr
576        .attrs
577        .iter()
578        .filter(|a| a.path.to_token_stream().to_string() == "int_result")
579        .map(|a| {
580            a.parse_args::<Ident>()
581                .unwrap_or_else(|_| format_ident!("Result"))
582        })
583        .next();
584
585    fn unwind_abi(attrs: &[impl AsRef<str>]) -> Option<bool> {
586        if cfg!(__cglue_force_no_unwind_abi) || attrs.iter().any(|i| i.as_ref() == "no_unwind_abi")
587        {
588            return Some(false);
589        }
590        if attrs.iter().any(|i| i.as_ref() == "unwind_abi") {
591            return Some(true);
592        }
593        None
594    }
595
596    let global_unwind_abi = unwind_abi(
597        &tr.attrs
598            .iter()
599            .map(|a| a.path.to_token_stream().to_string())
600            .collect::<Vec<_>>(),
601    );
602
603    // Parse all functions in the trait
604    for item in &tr.items {
605        match item {
606            // We assume types are defined before methods here...
607            TraitItem::Type(ty) => process_item(
608                (
609                    &Some(AssocType::new(ty.ident.clone(), ty.generics.clone())),
610                    &ty.bounds,
611                    ty.generics.where_clause.as_ref(),
612                    &ty.attrs,
613                ),
614                &tr.ident,
615                &generics,
616                &mut trait_type_defs,
617                &mut types,
618                &mut assocs,
619                crate_path,
620            ),
621            TraitItem::Method(m) => {
622                let attrs = m
623                    .attrs
624                    .iter()
625                    .map(|a| a.path.to_token_stream().to_string())
626                    .collect::<Vec<_>>();
627
628                if attrs.iter().any(|i| i == "skip_func") {
629                    continue;
630                }
631
632                let custom_impl = m
633                    .attrs
634                    .iter()
635                    .filter(|a| a.path.to_token_stream().to_string() == "custom_impl")
636                    .map(|a| a.parse_args::<CustomFuncImpl>().unwrap())
637                    .next();
638
639                let only_c_side = m
640                    .attrs
641                    .iter()
642                    .filter(|a| a.path.to_token_stream().to_string() == "vtbl_only")
643                    .map(|a| {
644                        a.parse_args::<PathTokens>().ok().map(
645                            |PathTokens {
646                                 lifetime,
647                                 path,
648                                 tokens,
649                             }| {
650                                (
651                                    lifetime,
652                                    Attribute {
653                                        pound_token: Default::default(),
654                                        style: AttrStyle::Outer,
655                                        bracket_token: Default::default(),
656                                        path,
657                                        tokens,
658                                    },
659                                )
660                            },
661                        )
662                    })
663                    .next();
664
665                let (only_c_side, types) = if let Some(attr) = only_c_side {
666                    if !also_parse_vtbl_only {
667                        continue;
668                    }
669
670                    types_c_side_vtbl.clear();
671                    if let Some((lt, attr)) = attr {
672                        let mut punctuated = Punctuated::default();
673
674                        if let Some(lt) = lt {
675                            punctuated.push_value(TypeParamBound::Lifetime(lt));
676                        }
677
678                        let attr_slice = std::slice::from_ref(&attr);
679                        process_item(
680                            (&None, &punctuated, None, attr_slice),
681                            &tr.ident,
682                            &generics,
683                            &mut trait_type_defs,
684                            &mut types_c_side_vtbl,
685                            &mut Default::default(),
686                            crate_path,
687                        );
688                    }
689                    (true, &types_c_side_vtbl)
690                } else {
691                    (false, &types)
692                };
693
694                let mut iter = m.sig.generics.params.iter();
695
696                if custom_impl.is_none() && iter.any(|p| !matches!(p, GenericParam::Lifetime(_))) {
697                    if m.default.is_none() {
698                        panic!("Generic function `{}` detected with neither a default nor custom implementation! This is not supported.", m.sig.ident);
699                    }
700                    continue;
701                }
702
703                let int_result_new = m
704                    .attrs
705                    .iter()
706                    .filter(|a| a.path.to_token_stream().to_string() == "int_result")
707                    .map(|a| {
708                        a.parse_args::<Ident>()
709                            .unwrap_or_else(|_| format_ident!("Result"))
710                    })
711                    .next();
712
713                let int_result = int_result_new.as_ref().or(int_result.as_ref());
714
715                funcs.extend(ParsedFunc::new(
716                    m.sig.clone(),
717                    trait_name.clone(),
718                    &generics,
719                    types,
720                    int_result,
721                    int_result
722                        .filter(|_| !attrs.iter().any(|i| i == "no_int_result"))
723                        .is_some(),
724                    crate_path,
725                    only_c_side,
726                    custom_impl,
727                    unwind_abi(&attrs)
728                        .or(global_unwind_abi)
729                        .unwrap_or(cfg!(feature = "unwind_abi_default")),
730                ));
731            }
732            _ => {}
733        }
734    }
735
736    let assoc_types = {
737        // CGlueA<X>: bounds, CGlueA<Y>: bounds, ...
738        let mut tokens = TokenStream::new();
739        // <X> = CGlueA<X>, <Y> = CGlueA<Y>, ...
740        let mut equality = TokenStream::new();
741
742        let mut assoc_vec = vec![];
743
744        // TODO: please, make this cleaner without reparsing tokens.
745        for (t, mut b) in assocs {
746            let t = t.ident;
747            let ident = format_ident!("CGlueA{}", t);
748            equality.extend(quote!(#t = #ident,));
749            if b.is_empty() {
750                tokens.extend(quote!(#ident,));
751            } else {
752                if !b.trailing_punct() {
753                    b.push_punct(Default::default());
754                }
755                tokens.extend(quote!(#ident: #b))
756            }
757            assoc_vec.push(t);
758        }
759
760        (parse2(quote!(<#tokens>)).unwrap(), assoc_vec, equality)
761    };
762
763    (funcs, generics, assoc_types, trait_type_defs)
764}
765
766pub fn gen_trait(mut tr: ItemTrait, ext_name: Option<&Ident>) -> TokenStream {
767    // Path to trait group import.
768    let crate_path = crate::util::crate_path();
769    let trg_path: TokenStream = quote!(#crate_path::trait_group);
770
771    // Need to preserve the same visibility as the trait itself.
772    let vis = tr.vis.to_token_stream();
773
774    let unsafety = tr.unsafety;
775    let trait_name = tr.ident.clone();
776    let trait_name = &trait_name;
777
778    let trait_impl_name = ext_name.unwrap_or(trait_name);
779
780    let c_void = crate::util::void_type();
781
782    // Additional identifiers
783    let vtbl_ident = format_ident!("{}Vtbl", trait_name);
784    let vtbl_get_ident = format_ident!("{}VtblGet", trait_name);
785    let ret_tmp_ident = format_ident!("{}RetTmp", trait_name);
786    let ret_tmp_ident_phantom = format_ident!("{}RetTmpPhantom", trait_name);
787    let accessor_trait_ident = format_ident!("{}OpaqueObj", trait_name);
788    let assoc_bind_ident = format_ident!("{}AssocBind", trait_name);
789
790    let base_box_trait_obj_ident = format_ident!("{}BaseBox", trait_name);
791    let base_ctx_trait_obj_ident = format_ident!("{}BaseCtxBox", trait_name);
792    let base_arc_trait_obj_ident = format_ident!("{}BaseArcBox", trait_name);
793    let base_mut_trait_obj_ident = format_ident!("{}BaseMut", trait_name);
794    let base_ctx_mut_trait_obj_ident = format_ident!("{}BaseCtxMut", trait_name);
795    let base_arc_mut_trait_obj_ident = format_ident!("{}BaseArcMut", trait_name);
796    let base_ref_trait_obj_ident = format_ident!("{}BaseRef", trait_name);
797    let base_ctx_ref_trait_obj_ident = format_ident!("{}BaseCtxRef", trait_name);
798    let base_arc_ref_trait_obj_ident = format_ident!("{}BaseArcRef", trait_name);
799    let base_trait_obj_ident = format_ident!("{}Base", trait_name);
800
801    let opaque_box_trait_obj_ident = format_ident!("{}Box", trait_name);
802    let opaque_ctx_trait_obj_ident = format_ident!("{}CtxBox", trait_name);
803    let opaque_arc_trait_obj_ident = format_ident!("{}ArcBox", trait_name);
804    let opaque_mut_trait_obj_ident = format_ident!("{}Mut", trait_name);
805    let opaque_ctx_mut_trait_obj_ident = format_ident!("{}CtxMut", trait_name);
806    let opaque_arc_mut_trait_obj_ident = format_ident!("{}ArcMut", trait_name);
807    let opaque_ref_trait_obj_ident = format_ident!("{}Ref", trait_name);
808    let opaque_ctx_ref_trait_obj_ident = format_ident!("{}CtxRef", trait_name);
809    let opaque_arc_ref_trait_obj_ident = format_ident!("{}ArcRef", trait_name);
810
811    let (funcs, generics, (assocs, assoc_idents, assoc_equality), trait_type_defs) =
812        parse_trait(&tr, &crate_path, true, process_item);
813
814    let cglue_c_opaque_bound = cglue_c_opaque_bound();
815    let ctx_bound = ctx_bound();
816
817    tr.ident = trait_impl_name.clone();
818
819    let mut trait_type_bounds = TokenStream::new();
820
821    let ParsedGenerics {
822        life_declare,
823        life_use,
824        gen_declare,
825        gen_use,
826        gen_where_bounds,
827        ..
828    } = &generics;
829
830    let ParsedGenerics {
831        gen_use: assoc_use,
832        gen_declare: assoc_declare,
833        ..
834    } = &assocs;
835
836    let assoc_declare_stripped = assocs.declare_without_nonstatic_bounds();
837
838    // TODO: Is there a better solution?
839    let cglue_a_outlives = if life_use.is_empty() {
840        None
841    } else {
842        let mut outlives = quote!(:);
843        for lt in life_use.iter() {
844            outlives.extend(quote!(#lt + ));
845        }
846        Some(outlives)
847    };
848
849    let gen_declare_stripped = generics.declare_without_nonstatic_bounds();
850    let gen_lt_bounds = generics.declare_lt_for_all(&quote!('cglue_a));
851    let gen_sabi_bounds = generics.declare_sabi_for_all(&crate_path);
852    let assoc_sabi_bounds = assocs.declare_sabi_for_all(&crate_path);
853
854    let gen_where_bounds_base_nolt = gen_where_bounds.clone();
855
856    let gen_where_bounds_base = quote! {
857        #gen_where_bounds
858        #gen_lt_bounds
859    };
860
861    let gen_where_bounds = quote! {
862        #gen_where_bounds_base
863        #gen_sabi_bounds
864        #assoc_sabi_bounds
865    };
866
867    #[cfg(feature = "layout_checks")]
868    let derive_layouts = quote!(#[derive(::abi_stable::StableAbi)]);
869    #[cfg(not(feature = "layout_checks"))]
870    let derive_layouts = quote!();
871
872    // Function definitions in the vtable
873    let mut vtbl_func_definitions = TokenStream::new();
874
875    for func in &funcs {
876        func.vtbl_def(&mut vtbl_func_definitions);
877    }
878
879    // Getters for vtable functions
880    let mut vtbl_getter_defintions = TokenStream::new();
881
882    for func in &funcs {
883        func.vtbl_getter_def(&mut vtbl_getter_defintions);
884    }
885
886    // Default functions for vtable reference
887    let mut vtbl_default_funcs = TokenStream::new();
888
889    for func in &funcs {
890        func.vtbl_default_def(&mut vtbl_default_funcs);
891    }
892
893    // Define wrapped functions for the vtable
894    let mut cfuncs = TokenStream::new();
895
896    let ret_tmp_ty = quote!(#ret_tmp_ident<CGlueCtx, #gen_use #assoc_use>);
897
898    for func in funcs.iter() {
899        let extra_bounds = func.cfunc_def(
900            &mut cfuncs,
901            &trg_path,
902            &ret_tmp_ty,
903            &assocs,
904            &assoc_equality,
905        );
906        trait_type_bounds.extend(extra_bounds.to_token_stream());
907    }
908
909    // Define wrapped temp storage
910    let mut ret_tmp_type_defs = TokenStream::new();
911
912    for func in funcs.iter() {
913        func.ret_tmp_def(&mut ret_tmp_type_defs);
914    }
915
916    // Define Default calls for temp storage
917    let mut ret_tmp_default_defs = TokenStream::new();
918
919    for func in funcs.iter() {
920        func.ret_default_def(&mut ret_tmp_default_defs);
921    }
922
923    // Define Default calls for temp storage
924    let mut ret_tmp_getter_defs = TokenStream::new();
925
926    for func in funcs.iter() {
927        func.ret_getter_def(&mut ret_tmp_getter_defs);
928    }
929
930    // Phantom data for temp storage including all types, because we do not
931    // actually know the types used inside the temp storage.
932    // I mean we could cross filter it but it's a little bit much work.
933    let phantom_data_definitions = generics.phantom_data_definitions();
934    let phantom_data_init = generics.phantom_data_init();
935    let assoc_phantom_data_definitions = assocs.phantom_data_definitions();
936    let assoc_phantom_data_init = assocs.phantom_data_init();
937
938    // Implement the trait for a type that has CGlueObj<OpaqueCGlueVtblT, RetTmp>
939    let mut trait_impl_fns = TokenStream::new();
940
941    // TODO: clean this up
942    let mut need_mut = false;
943    let mut need_own = false;
944    let mut need_cgluef = false;
945    let mut return_self = false;
946
947    for func in &funcs {
948        let (nm, no, rs) = func.trait_impl(&mut trait_impl_fns);
949        need_mut = nm || need_mut;
950        need_own = no || need_own;
951        need_cgluef = !no || need_cgluef;
952        return_self = rs || return_self;
953    }
954
955    let required_ctx = if need_mut {
956        quote!(#trg_path::CGlueObjMut<#ret_tmp_ty, Context = CGlueCtx> + )
957    } else {
958        quote!(#trg_path::CGlueObjRef<#ret_tmp_ty, Context = CGlueCtx> + )
959    };
960
961    let cglue_c_into_inner = if need_own {
962        Some(quote!(
963            CGlueC::InstType: #trg_path::IntoInner<InnerTarget = CGlueC::ObjType>,
964        ))
965    } else {
966        None
967    };
968
969    let cglue_c_bounds = quote!(: #required_ctx 'cglue_a);
970
971    // Add supertrait bounds here. Note that it probably won't work, unless they are one of the
972    // core traits (Send, etc.).
973    let supertrait_bounds = {
974        let sup = &tr.supertraits;
975        if sup.is_empty() {
976            quote!()
977        } else {
978            quote!(+ #sup)
979        }
980    };
981
982    // If wrapping an external trait, generate an internal implementation for CGlueTraitObj
983
984    let internal_trait_impl = if let Some(ext_name) = ext_name {
985        let mut impls = TokenStream::new();
986
987        for a in &assoc_idents {
988            impls.extend(quote!(type #a = <Self as #ext_name<#life_use #gen_use>>::#a;));
989        }
990
991        for func in &funcs {
992            func.int_trait_impl(None, ext_name, &mut impls);
993        }
994
995        quote! {
996            #unsafety impl<#life_declare CGlueT, CGlueV, CGlueC, CGlueR, #gen_declare> #trait_name<#life_use #gen_use>
997                for #trg_path::CGlueTraitObj<'_, CGlueT, CGlueV, CGlueC, CGlueR>
998            where
999                Self: #ext_name<#life_use #gen_use>
1000            {
1001                #impls
1002            }
1003        }
1004    } else {
1005        quote!()
1006    };
1007
1008    // Formatted documentation strings
1009    let vtbl_doc = format!(" CGlue vtable for trait {}.", trait_name);
1010
1011    let base_box_trait_obj_doc = format!(" Boxed CGlue trait object for trait {}.", trait_name);
1012    let base_ctx_trait_obj_doc = format!(
1013        " CtxBoxed CGlue trait object for trait {} with context.",
1014        trait_name
1015    );
1016    let base_arc_trait_obj_doc = format!(" Boxed CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.", trait_name);
1017    let base_mut_trait_obj_doc = format!(" By-mut CGlue trait object for trait {}.", trait_name);
1018    let base_ctx_mut_trait_obj_doc = format!(
1019        " By-mut CGlue trait object for trait {} with a context.",
1020        trait_name
1021    );
1022    let base_arc_mut_trait_obj_doc = format!(" By-mut CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.", trait_name);
1023    let base_ref_trait_obj_doc = format!(" By-ref CGlue trait object for trait {}.", trait_name);
1024    let base_ctx_ref_trait_obj_doc = format!(
1025        " By-ref CGlue trait object for trait {} with a context.",
1026        trait_name
1027    );
1028    let base_arc_ref_trait_obj_doc = format!(" By-ref CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.", trait_name);
1029    let base_trait_obj_doc = format!(" Base CGlue trait object for trait {}.", trait_name);
1030    let opaque_box_trait_obj_doc =
1031        format!(" Opaque Boxed CGlue trait object for trait {}.", trait_name);
1032    let opaque_ctx_trait_obj_doc = format!(
1033        " Opaque CtxBoxed CGlue trait object for trait {} with a context.",
1034        trait_name
1035    );
1036    let opaque_arc_trait_obj_doc = format!(" Opaque Boxed CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.", trait_name);
1037    let opaque_mut_trait_obj_doc = format!(
1038        " Opaque by-mut CGlue trait object for trait {}.",
1039        trait_name
1040    );
1041    let opaque_ctx_mut_trait_obj_doc = format!(
1042        " Opaque by-mut CGlue trait object for trait {} with a context.",
1043        trait_name
1044    );
1045    let opaque_arc_mut_trait_obj_doc = format!(
1046        " Opaque by-mut CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.",
1047        trait_name
1048    );
1049    let opaque_ref_trait_obj_doc = format!(
1050        " Opaque by-ref CGlue trait object for trait {}.",
1051        trait_name
1052    );
1053    let opaque_ctx_ref_trait_obj_doc = format!(
1054        " Opaque by-ref CGlue trait object for trait {} with a context.",
1055        trait_name
1056    );
1057    let opaque_arc_ref_trait_obj_doc = format!(
1058        " Opaque by-ref CGlue trait object for trait {} with a [`CArc`](cglue::arc::CArc) reference counted context.",
1059        trait_name
1060    );
1061    let submod_name = format_ident!("cglue_{}", trait_name.to_string().to_lowercase());
1062
1063    let ret_tmp = if !ret_tmp_type_defs.is_empty() {
1064        quote! {
1065            /// Temporary return value structure, for returning wrapped references.
1066            ///
1067            /// This structure contains data for each vtable function that returns a reference to
1068            /// an associated type. Note that these temporary values should not be accessed
1069            /// directly. Use the trait functions.
1070            #[repr(C)]
1071            #derive_layouts
1072            pub struct #ret_tmp_ident<CGlueCtx: #ctx_bound, #gen_use #assoc_use>
1073            {
1074                #ret_tmp_type_defs
1075                #phantom_data_definitions
1076                #assoc_phantom_data_definitions
1077                _ty_cglue_ctx: ::core::marker::PhantomData<CGlueCtx>,
1078            }
1079
1080            impl<CGlueCtx: #ctx_bound, #gen_use #assoc_use> #ret_tmp_ident<CGlueCtx, #gen_use #assoc_use>
1081            {
1082                #ret_tmp_getter_defs
1083            }
1084
1085            impl<CGlueCtx: #ctx_bound, #gen_use #assoc_use> Default for #ret_tmp_ident<CGlueCtx, #gen_use #assoc_use>
1086            {
1087                fn default() -> Self {
1088                    Self {
1089                        #ret_tmp_default_defs
1090                        #phantom_data_init
1091                        #assoc_phantom_data_init
1092                        _ty_cglue_ctx: ::core::marker::PhantomData,
1093                    }
1094                }
1095            }
1096        }
1097    } else {
1098        quote! {
1099            /// Technically unused phantom data definition structure.
1100            #[repr(C)]
1101            #derive_layouts
1102            pub struct #ret_tmp_ident_phantom<CGlueCtx: #ctx_bound, #gen_use #assoc_use>
1103            {
1104                #phantom_data_definitions
1105                #assoc_phantom_data_definitions
1106                _ty_cglue_ctx: ::core::marker::PhantomData<CGlueCtx>,
1107            }
1108
1109            /// Type definition for temporary return value wrapping storage.
1110            ///
1111            /// The trait does not use return wrapping, thus is a typedef to `PhantomData`.
1112            ///
1113            /// Note that `cbindgen` will generate wrong structures for this type. It is important
1114            /// to go inside the generated headers and fix it - all RetTmp structures without a
1115            /// body should be completely deleted, both as types, and as fields in the
1116            /// groups/objects. If C++11 templates are generated, it is important to define a
1117            /// custom type for CGlueTraitObj that does not have `ret_tmp` defined, and change all
1118            /// type aliases of this trait to use that particular structure.
1119            pub type #ret_tmp_ident<CGlueCtx, #gen_use #assoc_use> = ::core::marker::PhantomData<#ret_tmp_ident_phantom<CGlueCtx, #gen_use #assoc_use>>;
1120        }
1121    };
1122
1123    #[cfg(feature = "layout_checks")]
1124    let (opaque_vtbl_bounds, container_vtbl_bounds) = (
1125        quote!(#vtbl_ident<'cglue_a, CGlueC::OpaqueTarget, #gen_use #assoc_use>: ::abi_stable::StableAbi,),
1126        quote!(#vtbl_ident<'cglue_a, <Self as #trg_path::GetContainer>::ContType, #gen_use #assoc_use>: ::abi_stable::StableAbi,),
1127    );
1128    #[cfg(not(feature = "layout_checks"))]
1129    let (opaque_vtbl_bounds, container_vtbl_bounds) = (quote!(), quote!());
1130
1131    #[cfg(feature = "layout_checks")]
1132    let (layout_checkable_bound, objcont_accessor_bound) = (
1133        quote!(::abi_stable::StableAbi),
1134        quote!(<CGlueO as #trg_path::GetContainer>::ContType: ::abi_stable::StableAbi,),
1135    );
1136    #[cfg(not(feature = "layout_checks"))]
1137    let (layout_checkable_bound, objcont_accessor_bound) = (quote!(), quote!());
1138
1139    // Glue it all together
1140    quote! {
1141        #tr
1142
1143        #[doc(hidden)]
1144        #vis use #submod_name::*;
1145
1146        pub mod #submod_name {
1147            use super::*;
1148            use super::#trait_impl_name;
1149
1150            #vis use cglue_internal::{
1151                #vtbl_ident,
1152                #vtbl_get_ident,
1153                #ret_tmp_ident,
1154                #accessor_trait_ident,
1155                #assoc_bind_ident,
1156
1157                #base_box_trait_obj_ident,
1158                #base_ctx_trait_obj_ident,
1159                #base_arc_trait_obj_ident,
1160                #base_mut_trait_obj_ident,
1161                #base_ctx_mut_trait_obj_ident,
1162                #base_arc_mut_trait_obj_ident,
1163                #base_ref_trait_obj_ident,
1164                #base_ctx_ref_trait_obj_ident,
1165                #base_arc_ref_trait_obj_ident,
1166                #base_trait_obj_ident,
1167
1168                #opaque_box_trait_obj_ident,
1169                #opaque_ctx_trait_obj_ident,
1170                #opaque_arc_trait_obj_ident,
1171                #opaque_mut_trait_obj_ident,
1172                #opaque_ctx_mut_trait_obj_ident,
1173                #opaque_arc_mut_trait_obj_ident,
1174                #opaque_ref_trait_obj_ident,
1175                #opaque_ctx_ref_trait_obj_ident,
1176                #opaque_arc_ref_trait_obj_ident,
1177            };
1178
1179            mod cglue_internal {
1180            use super::*;
1181            use super::#trait_impl_name;
1182
1183            /* Primary vtable definition. */
1184
1185            #[doc = #vtbl_doc]
1186            ///
1187            /// This virtual function table contains ABI-safe interface for the given trait.
1188            #[repr(C)]
1189            #derive_layouts
1190            pub struct #vtbl_ident<
1191                'cglue_a,
1192                CGlueC: 'cglue_a + #trg_path::CGlueObjBase,
1193                #gen_declare_stripped
1194                #assoc_declare_stripped
1195            >
1196            where
1197                #gen_where_bounds_base_nolt
1198            {
1199                #vtbl_func_definitions
1200                #assoc_phantom_data_definitions
1201                _lt_cglue_a: ::core::marker::PhantomData<&'cglue_a CGlueC>,
1202            }
1203
1204            impl<
1205                'cglue_a,
1206                CGlueC: #trg_path::CGlueObjBase,
1207                #gen_declare_stripped
1208                #assoc_declare_stripped
1209            > #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>
1210            where
1211                #gen_where_bounds
1212            {
1213                #vtbl_getter_defintions
1214            }
1215
1216            #ret_tmp
1217
1218            /* Default implementation. */
1219
1220            /// Default vtable reference creation.
1221            impl<'cglue_a, CGlueC #cglue_c_bounds, CGlueCtx: #ctx_bound, #gen_declare_stripped #assoc_declare_stripped> Default
1222                for &'cglue_a #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>
1223            where #gen_where_bounds #trait_type_bounds #cglue_c_into_inner
1224                CGlueC::ObjType: for<#life_declare> #trait_name<#life_use #gen_use #assoc_equality>,
1225                CGlueC: #trg_path::Opaquable,
1226                CGlueC::OpaqueTarget: #trg_path::GenericTypeBounds,
1227                #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>: #trg_path::CGlueBaseVtbl,
1228            {
1229                /// Create a static vtable for the given type.
1230                fn default() -> Self {
1231                    &#vtbl_ident {
1232                        #vtbl_default_funcs
1233                        #assoc_phantom_data_init
1234                        _lt_cglue_a: ::core::marker::PhantomData,
1235                    }
1236                }
1237            }
1238
1239            /* Vtable trait implementations. */
1240
1241            impl<
1242                'cglue_a,
1243                CGlueC: #trg_path::CGlueObjBase,
1244                #gen_declare_stripped
1245                #assoc_declare_stripped
1246            >
1247                #trg_path::CGlueVtblCont for #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>
1248            where
1249                #gen_where_bounds
1250            {
1251                type ContType = CGlueC;
1252            }
1253
1254            unsafe impl<
1255                'cglue_a,
1256                CGlueC: #trg_path::Opaquable + #trg_path::CGlueObjBase + 'cglue_a,
1257                #gen_declare_stripped
1258                #assoc_declare_stripped
1259            > #trg_path::CGlueBaseVtbl
1260                for #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>
1261            where #gen_where_bounds #cglue_c_opaque_bound
1262                CGlueC::ObjType: for<#life_declare> #trait_name<#life_use #gen_use #assoc_equality>,
1263                CGlueC::OpaqueTarget: #trg_path::GenericTypeBounds,
1264                #opaque_vtbl_bounds
1265            {
1266                type OpaqueVtbl = #vtbl_ident<'cglue_a, CGlueC::OpaqueTarget, #gen_use #assoc_use>;
1267                type Context = CGlueC::Context;
1268                type RetTmp = #ret_tmp_ident<CGlueC::Context, #gen_use #assoc_use>;
1269            }
1270
1271            impl<'cglue_a, CGlueC #cglue_c_bounds, CGlueCtx: #ctx_bound, #gen_declare_stripped #assoc_declare_stripped> #trg_path::CGlueVtbl<CGlueC>
1272                for #vtbl_ident<'cglue_a, CGlueC, #gen_use #assoc_use>
1273            where #gen_where_bounds
1274                  #cglue_c_opaque_bound
1275                CGlueC: #trg_path::Opaquable,
1276                CGlueC::OpaqueTarget: #trg_path::GenericTypeBounds,
1277                CGlueC::ObjType: for<#life_declare> #trait_name<#life_use #gen_use #assoc_equality> {}
1278
1279            #[doc = #base_box_trait_obj_doc]
1280            pub type #base_box_trait_obj_ident<'cglue_a, CGlueT, #gen_use #assoc_use>
1281                = #base_trait_obj_ident<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, #trg_path::NoContext, #gen_use #assoc_use>;
1282
1283            #[doc = #base_ctx_trait_obj_doc]
1284            pub type #base_ctx_trait_obj_ident<'cglue_a, CGlueT, CGlueCtx, #gen_use #assoc_use>
1285                = #base_trait_obj_ident<'cglue_a, #crate_path::boxed::CBox<'cglue_a, CGlueT>, CGlueCtx, #gen_use #assoc_use>;
1286
1287            #[doc = #base_arc_trait_obj_doc]
1288            pub type #base_arc_trait_obj_ident<'cglue_a, CGlueT, CGlueC, #gen_use #assoc_use>
1289                = #base_ctx_trait_obj_ident<'cglue_a, CGlueT, #crate_path::arc::CArc<CGlueC>, #gen_use #assoc_use>;
1290
1291            #[doc = #base_mut_trait_obj_doc]
1292            pub type #base_mut_trait_obj_ident<'cglue_a, CGlueT, #gen_use #assoc_use>
1293                = #base_trait_obj_ident<'cglue_a, &'cglue_a mut CGlueT, #trg_path::NoContext, #gen_use #assoc_use>;
1294
1295            #[doc = #base_ctx_mut_trait_obj_doc]
1296            pub type #base_ctx_mut_trait_obj_ident<'cglue_a, CGlueT, CGlueCtx, #gen_use #assoc_use>
1297                = #base_trait_obj_ident<'cglue_a, &'cglue_a mut CGlueT, CGlueCtx, #gen_use #assoc_use>;
1298
1299            #[doc = #base_arc_mut_trait_obj_doc]
1300            pub type #base_arc_mut_trait_obj_ident<'cglue_a, CGlueT, CGlueC, #gen_use #assoc_use>
1301                = #base_trait_obj_ident<'cglue_a, &'cglue_a mut CGlueT, #crate_path::arc::CArc<CGlueC>, #gen_use #assoc_use>;
1302
1303            #[doc = #base_ref_trait_obj_doc]
1304            pub type #base_ref_trait_obj_ident<'cglue_a, CGlueT, #gen_use #assoc_use>
1305                = #base_trait_obj_ident<'cglue_a, &'cglue_a CGlueT, #trg_path::NoContext, #gen_use #assoc_use>;
1306
1307            #[doc = #base_ctx_ref_trait_obj_doc]
1308            pub type #base_ctx_ref_trait_obj_ident<'cglue_a, CGlueT, CGlueCtx, #gen_use #assoc_use>
1309                = #base_trait_obj_ident<'cglue_a, &'cglue_a CGlueT, CGlueCtx, #gen_use #assoc_use>;
1310
1311            #[doc = #base_arc_ref_trait_obj_doc]
1312            pub type #base_arc_ref_trait_obj_ident<'cglue_a, CGlueT, CGlueC, #gen_use #assoc_use>
1313                = #base_trait_obj_ident<'cglue_a, &'cglue_a CGlueT, #crate_path::arc::CArc<CGlueC>, #gen_use #assoc_use>;
1314
1315            #[doc = #base_trait_obj_doc]
1316            pub type #base_trait_obj_ident<'cglue_a, CGlueInst, CGlueCtx, #gen_use #assoc_use>
1317                = #trg_path::CGlueTraitObj::<
1318                    'cglue_a,
1319                    CGlueInst,
1320                    #vtbl_ident<
1321                        'cglue_a,
1322                        #trg_path::CGlueObjContainer<CGlueInst, CGlueCtx, #ret_tmp_ident<CGlueCtx, #gen_use #assoc_use>>,
1323                        #gen_use
1324                        #assoc_use
1325                    >,
1326                    CGlueCtx,
1327                    #ret_tmp_ident<CGlueCtx, #gen_use #assoc_use>
1328                >;
1329
1330            #[doc = #opaque_box_trait_obj_doc]
1331            pub type #opaque_box_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1332                = #base_box_trait_obj_ident<'cglue_a, #c_void, #gen_use #assoc_use>;
1333
1334            #[doc = #opaque_ctx_trait_obj_doc]
1335            pub type #opaque_ctx_trait_obj_ident<'cglue_a, CGlueCtx, #gen_use #assoc_use>
1336                = #base_ctx_trait_obj_ident<'cglue_a, #c_void, CGlueCtx, #gen_use #assoc_use>;
1337
1338            #[doc = #opaque_arc_trait_obj_doc]
1339            pub type #opaque_arc_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1340                = #base_arc_trait_obj_ident<'cglue_a, #c_void, #c_void, #gen_use #assoc_use>;
1341
1342            #[doc = #opaque_mut_trait_obj_doc]
1343            pub type #opaque_mut_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1344                = #base_mut_trait_obj_ident<'cglue_a, #c_void, #gen_use #assoc_use>;
1345
1346            #[doc = #opaque_ctx_mut_trait_obj_doc]
1347            pub type #opaque_ctx_mut_trait_obj_ident<'cglue_a, CGlueCtx, #gen_use #assoc_use>
1348                = #base_ctx_mut_trait_obj_ident<'cglue_a, #c_void, CGlueCtx, #gen_use #assoc_use>;
1349
1350            #[doc = #opaque_arc_mut_trait_obj_doc]
1351            pub type #opaque_arc_mut_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1352                = #base_arc_mut_trait_obj_ident<'cglue_a, #c_void, #c_void, #gen_use #assoc_use>;
1353
1354            #[doc = #opaque_ref_trait_obj_doc]
1355            pub type #opaque_ref_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1356                = #base_ref_trait_obj_ident<'cglue_a, #c_void, #gen_use #assoc_use>;
1357
1358            #[doc = #opaque_ctx_ref_trait_obj_doc]
1359            pub type #opaque_ctx_ref_trait_obj_ident<'cglue_a, CGlueCtx, #gen_use #assoc_use>
1360                = #base_ctx_ref_trait_obj_ident<'cglue_a, #c_void, CGlueCtx, #gen_use #assoc_use>;
1361
1362            #[doc = #opaque_arc_ref_trait_obj_doc]
1363            pub type #opaque_arc_ref_trait_obj_ident<'cglue_a, #gen_use #assoc_use>
1364                = #base_arc_ref_trait_obj_ident<'cglue_a, #c_void, #c_void, #gen_use #assoc_use>;
1365
1366            /* Internal wrapper functions. */
1367
1368            #cfuncs
1369
1370            /* Define trait for simpler type accesses */
1371
1372            pub trait #accessor_trait_ident<'cglue_a #cglue_a_outlives, #life_declare #gen_declare #assoc_declare>
1373                : 'cglue_a + #trg_path::GetContainer + #vtbl_get_ident<'cglue_a, #gen_use #assoc_use> #supertrait_bounds
1374            where
1375                #gen_where_bounds
1376            {
1377                type #vtbl_ident: #trg_path::CGlueVtblCont<ContType = <Self as #trg_path::GetContainer>::ContType> + #layout_checkable_bound;
1378            }
1379
1380            impl<'cglue_a #cglue_a_outlives, #life_declare
1381                CGlueO: 'cglue_a + #trg_path::GetContainer + #vtbl_get_ident<'cglue_a, #gen_use #assoc_use> #supertrait_bounds, #gen_declare #assoc_declare>
1382                #accessor_trait_ident<'cglue_a, #life_use #gen_use #assoc_use> for CGlueO
1383            where
1384                #objcont_accessor_bound
1385                #gen_where_bounds
1386            {
1387                type #vtbl_ident = #vtbl_ident<'cglue_a, <Self as #trg_path::GetContainer>::ContType, #gen_use #assoc_use>;
1388            }
1389
1390            /* Binds associated types for a given trait. */
1391
1392            pub trait #assoc_bind_ident<#gen_use> {
1393                type Assocs;
1394            }
1395
1396            impl<
1397                'cglue_a,
1398                CGlueT: ::core::ops::Deref<Target = CGlueF>,
1399                CGlueF,
1400                CGlueCtx: #ctx_bound,
1401                CGlueRetTmp,
1402                #gen_declare_stripped
1403                #assoc_declare_stripped
1404            >
1405                #assoc_bind_ident<#gen_use>
1406                for #trg_path::CGlueTraitObj<'cglue_a, CGlueT, #vtbl_ident<'cglue_a, #trg_path::CGlueObjContainer<CGlueT, CGlueCtx, CGlueRetTmp>, #gen_use #assoc_use>, CGlueCtx, CGlueRetTmp>
1407            where
1408                #gen_where_bounds_base
1409            {
1410                type Assocs = (#assoc_use);
1411            }
1412
1413            /* Getters for vtables. Automatically implemented for CGlueTraitObj */
1414
1415            pub trait #vtbl_get_ident<'cglue_a, #gen_declare_stripped #assoc_declare_stripped>:
1416                #trg_path::GetContainer
1417            where
1418                #gen_where_bounds_base
1419            {
1420                fn get_vtbl(&self) -> &#vtbl_ident<'cglue_a, <Self as #trg_path::GetContainer>::ContType, #gen_use #assoc_use>;
1421            }
1422
1423            impl<
1424                'cglue_a,
1425                CGlueT: ::core::ops::Deref<Target = CGlueF>,
1426                CGlueF,
1427                CGlueCtx: #ctx_bound,
1428                CGlueRetTmp,
1429                #gen_declare_stripped
1430                #assoc_declare_stripped
1431            >
1432                #vtbl_get_ident<'cglue_a, #gen_use #assoc_use>
1433                for #trg_path::CGlueTraitObj<'cglue_a, CGlueT, #vtbl_ident<'cglue_a, #trg_path::CGlueObjContainer<CGlueT, CGlueCtx, CGlueRetTmp>, #gen_use #assoc_use>, CGlueCtx, CGlueRetTmp>
1434            where
1435                #gen_where_bounds_base
1436            {
1437                fn get_vtbl(&self) -> &#vtbl_ident<'cglue_a, <Self as #trg_path::GetContainer>::ContType, #gen_use #assoc_use> {
1438                    #trg_path::GetVtblBase::get_vtbl_base(self)
1439                }
1440            }
1441
1442            /* Trait implementation. */
1443
1444            #unsafety impl<'cglue_a #cglue_a_outlives, #life_declare
1445                CGlueO: 'cglue_a + #vtbl_get_ident<'cglue_a, #gen_use #assoc_use> #supertrait_bounds
1446                    // We essentially need only this bound, but we repeat the previous ones because
1447                    // otherwise we get conflicting impl errors.
1448                    // TODO: Is this a bug? Typically Rust typesystem doesn't complain in such cases.
1449                    + #accessor_trait_ident<'cglue_a, #life_use #gen_use #assoc_use>
1450                    // Same here.
1451                    + #assoc_bind_ident<#gen_use Assocs = (#assoc_use)>
1452                    // We also need to specify this one, for some reason. If not for conflicting
1453                    // impl errors, `GetVtblBase` would be a relatively redundant trait with no
1454                    // purpose.
1455                    + #trg_path::GetVtblBase<#vtbl_ident<'cglue_a, <Self as #trg_path::GetContainer>::ContType, #gen_use #assoc_use>>,
1456            #gen_declare #assoc_declare>
1457                #trait_impl_name<#life_use #gen_use> for CGlueO
1458            where
1459                #gen_where_bounds
1460                #container_vtbl_bounds
1461            {
1462                // TODO: #assoc_type_def
1463                #trait_type_defs
1464                #trait_impl_fns
1465            }
1466
1467            #internal_trait_impl
1468            }
1469        }
1470    }
1471}