cglue_gen/
func.rs

1use super::generics::{GenericType, ParsedGenerics};
2use super::util::parse_brace_content;
3use crate::util::{merge_lifetime_declarations, remap_lifetime_defs, remap_type_lifetimes};
4use proc_macro2::TokenStream;
5use quote::*;
6use std::cmp::Ordering;
7use std::collections::BTreeMap;
8use syn::{parse::*, punctuated::Punctuated, token::Comma, Type, *};
9
10const FN_PREFIX: &str = "cglue_wrapped_";
11
12pub struct WrappedType {
13    pub ty: GenericType,
14    pub ty_ret_tmp: Option<GenericType>,
15    pub ty_static: Option<GenericType>,
16    pub lifetime_bound: Option<Lifetime>,
17    pub lifetime_type_bound: Option<Lifetime>,
18    pub other_bounds: Option<TokenStream>,
19    pub other_bounds_simple: Option<TokenStream>,
20    pub return_conv: Option<ExprClosure>,
21    pub impl_return_conv: Option<TokenStream>,
22    pub inject_ret_tmp: bool,
23    pub unbounded_hrtb: bool,
24}
25
26#[derive(Eq, PartialEq, Clone)]
27pub struct AssocType {
28    pub ident: Ident,
29    pub generics: Generics,
30}
31
32impl AssocType {
33    /// Remap the associated type for use within HRTB bounds.
34    ///
35    /// Currently the only supported configuration is a single generic lifetime.
36    ///
37    /// # Panics
38    ///
39    /// If generic types are not supported for remapping.
40    pub fn remap_for_hrtb(&self) -> Self {
41        let mut params = self.generics.params.iter();
42        match (params.next(), params.next()) {
43            (Some(GenericParam::Lifetime(_)), None) => Self {
44                ident: self.ident.clone(),
45                generics: syn::parse2(quote!(<'cglue_b>)).unwrap(),
46            },
47            (None, _) => self.clone(),
48            _ => panic!("Unsupported generic parameter configuration!"),
49        }
50    }
51}
52
53impl ToTokens for AssocType {
54    fn to_tokens(&self, tokens: &mut TokenStream) {
55        self.ident.to_tokens(tokens);
56        self.generics.to_tokens(tokens);
57    }
58}
59
60impl PartialOrd for AssocType {
61    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
62        Some(self.cmp(other))
63    }
64}
65
66impl Ord for AssocType {
67    fn cmp(&self, other: &Self) -> Ordering {
68        self.ident.cmp(&other.ident)
69    }
70}
71
72impl From<Ident> for AssocType {
73    fn from(ident: Ident) -> Self {
74        Self {
75            ident,
76            generics: Default::default(),
77        }
78    }
79}
80
81impl AssocType {
82    pub fn new(ident: Ident, generics: Generics) -> Self {
83        Self { ident, generics }
84    }
85}
86
87pub struct CustomFuncImpl {
88    pub tys: Punctuated<FnArg, Comma>,
89    pub c_ret_ty: ReturnType,
90    pub pre_call_impl: TokenStream,
91    pub c_inner_body: Option<TokenStream>,
92    pub impl_func_ret: Option<TokenStream>,
93}
94
95#[derive(Default)]
96struct CustomFuncConv {
97    pub pre_call_impl: TokenStream,
98    pub c_inner_body: Option<TokenStream>,
99    pub impl_func_ret: Option<TokenStream>,
100}
101
102impl Parse for CustomFuncImpl {
103    fn parse(input: ParseStream) -> Result<Self> {
104        let content = parse_brace_content(input)?;
105        let tys = Punctuated::parse_terminated(&content)?;
106
107        input.parse::<Token![,]>()?;
108
109        let c_ret_ty = ReturnType::Type(Default::default(), input.parse::<Type>()?.into());
110
111        input.parse::<Token![,]>()?;
112
113        let pre_call_impl: TokenStream = parse_brace_content(input)?.parse()?;
114        input.parse::<Token![,]>()?;
115
116        let c_inner_body: TokenStream = parse_brace_content(input)?.parse()?;
117        let c_inner_body = if c_inner_body.is_empty() {
118            None
119        } else {
120            Some(quote!( { #c_inner_body } ))
121        };
122        input.parse::<Token![,]>()?;
123
124        let impl_func_ret: TokenStream = parse_brace_content(input)?.parse()?;
125        let impl_func_ret = if impl_func_ret.is_empty() {
126            None
127        } else {
128            Some(quote!( { #impl_func_ret } ))
129        };
130
131        input.parse::<Token![,]>().ok();
132
133        Ok(Self {
134            tys,
135            c_ret_ty,
136            pre_call_impl,
137            c_inner_body,
138            impl_func_ret,
139        })
140    }
141}
142
143/// TraitArgConv stores implementations for Unstable-C-Unstable ABI transitions.
144struct TraitArgConv {
145    /// Called in trait impl to define arguments. Useful when need to destruct a tuple/struct.
146    to_c_args: TokenStream,
147    /// Arguments inside the call to the C vtable function.
148    call_c_args: TokenStream,
149    /// C function signature.
150    c_args: TokenStream,
151    /// C function signature, where 'cglue_a lifetimes are replaced with 'cglue_b.
152    c_cast_args: TokenStream,
153    /// Arguments inside the call to the trait function.
154    to_trait_arg: TokenStream,
155}
156
157fn ret_wrap_type<'a>(
158    ty: &mut Type,
159    targets: &'a BTreeMap<Option<AssocType>, WrappedType>,
160) -> Option<(Type, Option<AssocType>, &'a WrappedType)> {
161    // None means handle only the C side - the function will not be called on Rust side.
162    // This is useful for providing functionality for C users that can be done faster in Rust.
163    // TODO: perhaps switch targets to an enum to indicate C side or not.
164    if let Some(wrapped) = targets.get(&None) {
165        let WrappedType { ty: new_ty, .. } = wrapped;
166
167        let ret = std::mem::replace(
168            ty,
169            syn::parse2(new_ty.to_token_stream()).expect("Failed to parse wrap_type"),
170        );
171
172        Some((ret, None, wrapped))
173    } else {
174        do_wrap_type(ty, targets)
175    }
176}
177
178fn do_wrap_type<'a>(
179    ty: &mut Type,
180    targets: &'a BTreeMap<Option<AssocType>, WrappedType>,
181) -> Option<(Type, Option<AssocType>, &'a WrappedType)> {
182    match ty {
183        Type::Reference(r) => do_wrap_type(&mut r.elem, targets),
184        Type::Slice(s) => do_wrap_type(&mut s.elem, targets),
185        Type::Path(p) => {
186            let mut iter = p.path.segments.iter();
187            match (&p.qself, p.path.leading_colon, iter.next(), iter.next()) {
188                (None, None, Some(p1), Some(p2)) => {
189                    if p1.ident == "Self" {
190                        if let Some(wrapped) = targets.get(&Some(p2.ident.clone().into())) {
191                            let WrappedType { ty: new_ty, .. } = wrapped;
192
193                            std::mem::drop(iter);
194
195                            let ident = p2.ident.clone();
196                            let generics: Generics = syn::parse2(p2.arguments.to_token_stream())
197                                .expect("Failed to parse generics");
198
199                            let ret = std::mem::replace(
200                                ty,
201                                syn::parse2(new_ty.to_token_stream())
202                                    .expect("Failed to parse wrap_type"),
203                            );
204
205                            return Some((ret, Some(AssocType::new(ident, generics)), wrapped));
206                        }
207                    }
208                }
209                (None, None, Some(p1), None) => {
210                    if p1.ident == "Self" {
211                        let self_return_wrap = targets
212                            .get(&Some(p1.ident.clone().into()))
213                            .expect("No self-wrap rule specified");
214                        let WrappedType { ty: new_ty, .. } = self_return_wrap;
215
216                        std::mem::drop(iter);
217
218                        let ident = p1.ident.clone();
219                        // Self has no type parameters, right?
220
221                        let ret = std::mem::replace(
222                            ty,
223                            syn::parse2(new_ty.to_token_stream())
224                                .expect("Failed to parse self-type wrap"),
225                        );
226
227                        return Some((ret, Some(ident.into()), self_return_wrap));
228                    }
229                }
230                _ => {}
231            }
232
233            std::mem::drop(iter);
234
235            for seg in p.path.segments.iter_mut() {
236                if let PathArguments::AngleBracketed(brac) = &mut seg.arguments {
237                    for arg in brac.args.iter_mut() {
238                        if let GenericArgument::Type(ty) = arg {
239                            let ret = do_wrap_type(ty, targets);
240                            if ret.is_some() {
241                                return ret;
242                            }
243                        }
244                    }
245                }
246            }
247
248            None
249        }
250        Type::Ptr(ptr) => do_wrap_type(&mut ptr.elem, targets),
251        Type::Tuple(tup) => tup.elems.iter_mut().find_map(|e| do_wrap_type(e, targets)),
252        // TODO: Other types
253        _ => None,
254    }
255}
256
257impl TraitArgConv {
258    fn new(
259        arg: &FnArg,
260        targets: &BTreeMap<Option<AssocType>, WrappedType>,
261        crate_path: &TokenStream,
262        inject_lifetime: Option<&Lifetime>,
263        inject_lifetime_cast: Option<&Lifetime>,
264        lifetime_map: &BTreeMap<Lifetime, Lifetime>,
265    ) -> Self {
266        let (to_c_args, call_c_args, c_args, c_cast_args, to_trait_arg) = match arg {
267            FnArg::Receiver(r) => {
268                let lifetime = inject_lifetime.or_else(|| r.lifetime());
269                let lifetime_cast = inject_lifetime_cast.or_else(|| r.lifetime());
270
271                if r.reference.is_none() {
272                    (
273                        quote! {
274                            let cont = self.into_ccont();
275                            // Guard against failure cases where context drops the library.
276                            // Only happens where self gets consumed.
277                            // TODO: make a breaking change in cobj_owned so this is not needed
278                            // separately
279                            // TODO 2: figure out how to test this.
280                            let __ctx = #crate_path::trait_group::CGlueObjBase::cobj_base_ref(&cont).1.clone();
281                        },
282                        quote!(cont,),
283                        quote!(cont: CGlueC,),
284                        quote!(cont: CGlueC,),
285                        quote!(),
286                    )
287                } else if r.mutability.is_some() {
288                    (
289                        quote!(let cont = self.ccont_mut();),
290                        quote!(cont,),
291                        quote!(cont: &#lifetime mut CGlueC,),
292                        quote!(cont: &#lifetime_cast mut CGlueC,),
293                        quote!(),
294                    )
295                } else {
296                    (
297                        quote!(let cont = self.ccont_ref();),
298                        quote!(cont,),
299                        quote!(cont: &#lifetime CGlueC,),
300                        quote!(cont: &#lifetime_cast CGlueC,),
301                        quote!(),
302                    )
303                }
304            }
305            t if recv_pin(t) => {
306                let lifetime = inject_lifetime.or_else(|| recv_lifetime(t));
307                let lifetime_cast = inject_lifetime_cast.or_else(|| recv_lifetime(t));
308
309                if recv_mutable(t) {
310                    (
311                        quote!(let cont = self.ccont_pin_mut();),
312                        quote!(cont,),
313                        quote!(cont: ::core::pin::Pin<&#lifetime mut CGlueC>,),
314                        quote!(cont: ::core::pin::Pin<&#lifetime_cast mut CGlueC>,),
315                        quote!(),
316                    )
317                } else {
318                    (
319                        quote!(let cont = self.ccont_pin_ref();),
320                        quote!(cont,),
321                        quote!(cont: ::core::pin::Pin<&#lifetime CGlueC>,),
322                        quote!(cont: ::core::pin::Pin<&#lifetime_cast CGlueC>,),
323                        quote!(),
324                    )
325                }
326            }
327            FnArg::Typed(t) => {
328                let mut t = t.clone();
329                let _old = do_wrap_type(&mut t.ty, targets);
330
331                let name = &*t.pat;
332
333                // TODO: handle more edge cases here
334                let name = match name {
335                    Pat::Ident(id) => id.ident.to_token_stream(),
336                    x => quote!(#x),
337                };
338
339                let ty = &*t.ty;
340
341                let mut ret = None;
342
343                // Map all lifetimes
344                let mut ty = ty.clone();
345                remap_type_lifetimes(&mut ty, lifetime_map);
346
347                // TODO: deal with nested conversion
348                //if let (Some(old), Type::Path(p)) = {
349                //}
350
351                match &ty {
352                    Type::Reference(r) => {
353                        let is_mut = r.mutability.is_some();
354
355                        let lt = r
356                            .lifetime
357                            .as_ref()
358                            .map(|lt| lifetime_map.get(lt).unwrap_or(lt))
359                            .map(|v| quote!(#v,));
360
361                        let new_ty = match &*r.elem {
362                            Type::Slice(s) => {
363                                let ty = &*s.elem;
364                                Some(if is_mut {
365                                    quote!(#crate_path::slice::CSliceMut<#lt #ty>)
366                                } else {
367                                    quote!(#crate_path::slice::CSliceRef<#lt #ty>)
368                                })
369                                .map(|v| (v, false))
370                            }
371                            Type::Path(p) => if let Some("str") =
372                                p.path.get_ident().map(|i| i.to_string()).as_deref()
373                            {
374                                Some(if is_mut {
375                                    quote!(#crate_path::slice::CSliceMut<#lt u8>)
376                                } else {
377                                    quote!(#crate_path::slice::CSliceRef<#lt u8>)
378                                })
379                            } else {
380                                None
381                            }
382                            .map(|v| (v, true)),
383                            _ => None,
384                        };
385
386                        if let Some((slty, into_str)) = new_ty {
387                            ret = Some((
388                                quote!(),
389                                quote!(#name.into(),),
390                                quote!(#name: #slty,),
391                                quote!(#name: #slty,),
392                                if into_str {
393                                    quote!(unsafe { #name.into_str() },)
394                                } else {
395                                    quote!(#name.into(),)
396                                },
397                            ))
398                        }
399                    }
400                    // TODO: Warn if Box is being used.
401                    Type::Path(p) => {
402                        // Here we check for any Option types, and wrap them to COption if they can
403                        // not be NPOd.
404                        let last = p.path.segments.last();
405                        if let Some((PathArguments::AngleBracketed(args), last)) =
406                            last.map(|l| (&l.arguments, l))
407                        {
408                            match last.ident.to_string().as_str() {
409                                "Option" => {
410                                    if let Some(GenericArgument::Type(a)) = args.args.first() {
411                                        if !crate::util::is_null_pointer_optimizable(a, &[]) {
412                                            ret = Some((
413                                                quote!(let #name = #name.into();),
414                                                quote!(#name,),
415                                                quote!(#name: #crate_path::option::COption<#a>,),
416                                                quote!(#name: #crate_path::option::COption<#a>,),
417                                                quote!(#name.into(),),
418                                            ));
419                                        }
420                                    }
421                                }
422                                "Result" => {
423                                    let mut args = args.args.iter();
424
425                                    match (args.next(), args.next(), args.next(), false) {
426                                        (Some(GenericArgument::Type(_)), _, None, true) => {
427                                            // TODO: Wrap Result<T> alias to use int values if it is marked
428                                            // to implement IntResult
429                                        }
430                                        (
431                                            Some(GenericArgument::Type(a)),
432                                            Some(GenericArgument::Type(b)),
433                                            None,
434                                            _,
435                                        ) => {
436                                            ret = Some((
437                                                quote!(let #name = #name.into();),
438                                                quote!(#name,),
439                                                quote!(#name: #crate_path::result::CResult<#a, #b>,),
440                                                quote!(#name: #crate_path::result::CResult<#a, #b>,),
441                                                quote!(#name.into(),),
442                                            ));
443                                        }
444                                        _ => {}
445                                    }
446                                }
447                                _ => {}
448                            }
449                        }
450                    }
451                    Type::ImplTrait(t) => {
452                        // Convert `impl Into<T>` to `T`.
453                        if t.bounds.len() == 1 {
454                            if let TypeParamBound::Trait(t) = t.bounds.first().unwrap() {
455                                if t.path.segments.len() == 1 {
456                                    let seg = t.path.segments.first().unwrap();
457                                    if seg.ident == format_ident!("Into") {
458                                        if let PathArguments::AngleBracketed(a) = &seg.arguments {
459                                            if a.args.len() == 1 {
460                                                let ty = a.args.first().unwrap();
461
462                                                ret = Some((
463                                                    quote!(let #name = #name.into();),
464                                                    quote!(#name,),
465                                                    quote!(#name: #ty,),
466                                                    quote!(#name: #ty,),
467                                                    quote!(#name,),
468                                                ))
469                                            }
470                                        }
471                                    }
472                                }
473                            }
474                        }
475                    }
476                    _ => {}
477                }
478
479                ret.unwrap_or_else(|| {
480                    (
481                        quote!(let #name = #name;),
482                        quote!(#name,),
483                        quote!(#name: #ty,),
484                        quote!(#name: #ty,),
485                        quote!(#name,),
486                    )
487                })
488            }
489        };
490
491        Self {
492            to_c_args,
493            call_c_args,
494            c_args,
495            c_cast_args,
496            to_trait_arg,
497        }
498    }
499}
500
501pub struct ParsedFunc {
502    name: Ident,
503    trait_name: Ident,
504    safe: bool,
505    abi: FuncAbi,
506    unwind_safe: bool,
507    receiver: FnArg,
508    orig_args: Vec<FnArg>,
509    args: Vec<TraitArgConv>,
510    out: ParsedReturnType,
511    generics: ParsedGenerics,
512    sig_generics: ParsedGenerics,
513    custom_conv: CustomFuncConv,
514    only_c_side: bool,
515}
516
517fn extract_pin(t: &Type) -> Option<&Type> {
518    if let Type::Path(v) = t {
519        if let Some(seg) = v.path.segments.last() {
520            if seg.ident != "Pin" {
521                return None;
522            }
523            if let PathArguments::AngleBracketed(a) = &seg.arguments {
524                if a.args.len() == 1 {
525                    let a = a.args.first()?;
526                    if let GenericArgument::Type(t) = a {
527                        return Some(t);
528                    }
529                }
530            }
531        }
532    }
533    None
534}
535
536fn recv_pin(recv: &FnArg) -> bool {
537    match recv {
538        FnArg::Receiver(_) => false,
539        FnArg::Typed(t) => matches!(extract_pin(&t.ty), Some(Type::Reference(_))),
540    }
541}
542
543fn recv_lifetime(recv: &FnArg) -> Option<&Lifetime> {
544    match recv {
545        FnArg::Receiver(r) => r.lifetime(),
546        FnArg::Typed(t) => {
547            if let Some(Type::Reference(r)) = extract_pin(&t.ty) {
548                r.lifetime.as_ref()
549            } else {
550                None
551            }
552        }
553    }
554}
555
556fn recv_reference(recv: &FnArg) -> bool {
557    match recv {
558        FnArg::Receiver(r) => r.reference.is_some(),
559        FnArg::Typed(t) => matches!(extract_pin(&t.ty), Some(Type::Reference(_))),
560    }
561}
562
563fn recv_mutable(recv: &FnArg) -> bool {
564    match recv {
565        FnArg::Receiver(r) => r.mutability.is_some(),
566        FnArg::Typed(t) => matches!(
567            extract_pin(&t.ty),
568            Some(Type::Reference(TypeReference {
569                mutability: Some(_),
570                ..
571            }))
572        ),
573    }
574}
575
576impl ParsedFunc {
577    #[allow(clippy::too_many_arguments)]
578    pub fn new(
579        sig: Signature,
580        trait_name: Ident,
581        generics: &ParsedGenerics,
582        wrap_types: &BTreeMap<Option<AssocType>, WrappedType>,
583        res_override: Option<&Ident>,
584        int_result: bool,
585        crate_path: &TokenStream,
586        only_c_side: bool,
587        custom_impl: Option<CustomFuncImpl>,
588        unwind_safe: bool,
589    ) -> Option<Self> {
590        let name = sig.ident;
591        let safe = sig.unsafety.is_none();
592        let abi = From::from(sig.abi);
593        let mut args: Vec<TraitArgConv> = vec![];
594        let mut orig_args = vec![];
595
596        let mut receiver = None;
597
598        let unsafety = if safe { quote!(unsafe) } else { quote!() };
599
600        for input in sig.inputs.iter() {
601            match &input {
602                FnArg::Receiver(_) => {
603                    receiver = Some(input.clone());
604                }
605                FnArg::Typed(v) => {
606                    if let Pat::Ident(ref i) = *v.pat {
607                        if i.ident == "self" {
608                            receiver = Some(input.clone());
609                        }
610                    }
611                }
612            }
613        }
614
615        let receiver = receiver?;
616
617        let out = ParsedReturnType::new(
618            (sig.output, custom_impl.as_ref().map(|i| &i.c_ret_ty)),
619            wrap_types,
620            res_override,
621            int_result,
622            &unsafety,
623            (&name, &receiver),
624            (crate_path, &trait_name, generics),
625        );
626
627        // If a custom impl is provided, use its arguments
628        let custom_conv = if let Some(CustomFuncImpl {
629            tys,
630            pre_call_impl,
631            c_inner_body,
632            impl_func_ret,
633            ..
634        }) = custom_impl
635        {
636            orig_args.extend(sig.inputs.into_iter());
637            // But first, we need to process the receiver (self) type, as it is implicit.
638            for arg in orig_args
639                .iter()
640                .filter(|a| match a {
641                    FnArg::Receiver(_) => true,
642                    FnArg::Typed(v) => {
643                        if let Pat::Ident(ref i) = *v.pat {
644                            if i.ident == "self" {
645                                return true;
646                            }
647                        }
648                        false
649                    }
650                })
651                .take(1)
652                .chain(tys.iter())
653            {
654                args.push(TraitArgConv::new(
655                    arg,
656                    wrap_types,
657                    crate_path,
658                    out.lifetime.as_ref(),
659                    out.lifetime_cast.as_ref(),
660                    &out.lifetime_map,
661                ));
662            }
663
664            CustomFuncConv {
665                pre_call_impl,
666                c_inner_body,
667                impl_func_ret,
668            }
669        } else {
670            for input in sig.inputs.into_iter() {
671                let func = TraitArgConv::new(
672                    &input,
673                    wrap_types,
674                    crate_path,
675                    out.lifetime.as_ref(),
676                    out.lifetime_cast.as_ref(),
677                    &out.lifetime_map,
678                );
679
680                args.push(func);
681                orig_args.push(input);
682            }
683
684            Default::default()
685        };
686
687        let generics = generics.clone();
688
689        let sig_generics = ParsedGenerics::from(&sig.generics);
690
691        Some(Self {
692            name,
693            trait_name,
694            safe,
695            abi,
696            unwind_safe,
697            receiver,
698            orig_args,
699            args,
700            out,
701            generics,
702            sig_generics,
703            only_c_side,
704            custom_conv,
705        })
706    }
707
708    pub fn ret_tmp_def(&self, stream: &mut TokenStream) {
709        let name = &self.name;
710        // If injected_ret_tmp exists, try using the static one, but skip it if it doesn't exist.
711        if let (Some(_), Some(ty)) = (
712            &self.out.injected_ret_tmp,
713            self.out
714                .injected_ret_tmp_static
715                .as_ref()
716                .or(self.out.injected_ret_tmp.as_ref()),
717        ) {
718            let gen = if recv_mutable(&self.receiver) {
719                quote!(#name: ::core::mem::MaybeUninit<#ty>,)
720            } else {
721                quote!(#name: ::core::cell::Cell<::core::mem::MaybeUninit<#ty>>,)
722            };
723            stream.extend(gen);
724        }
725    }
726
727    pub fn ret_default_def(&self, stream: &mut TokenStream) {
728        let name = &self.name;
729        if self.out.injected_ret_tmp.is_some() {
730            let gen = if recv_mutable(&self.receiver) {
731                quote!(#name: ::core::mem::MaybeUninit::uninit(),)
732            } else {
733                quote!(#name: ::core::cell::Cell::new(::core::mem::MaybeUninit::uninit()),)
734            };
735            stream.extend(gen);
736        }
737    }
738
739    pub fn ret_getter_def(&self, stream: &mut TokenStream) {
740        let name = &self.name;
741
742        if let Some(ty) = &self.out.injected_ret_tmp {
743            let gen = match (&self.out.lifetime, recv_mutable(&self.receiver)) {
744                (Some(lt), true) => {
745                    quote! {
746                        fn #name<#lt>(&#lt mut self) -> &#lt mut ::core::mem::MaybeUninit<#ty> {
747                            // SAFETY:
748                            // We shorten the lifetime of the borrowed data.
749                            // The data is not being dropped, and is not accessible
750                            // from anywhere else, so this is safe.:w
751                            unsafe { std::mem::transmute(&mut self.#name) }
752                        }
753                    }
754                }
755                (None, true) => {
756                    quote! {
757                        fn #name(&mut self) -> &mut ::core::mem::MaybeUninit<#ty> {
758                            &mut self.#name
759                        }
760                    }
761                }
762                (Some(lt), false) => {
763                    quote! {
764                        #[allow(clippy::mut_from_ref)]
765                        fn #name<#lt>(&#lt self) -> &#lt mut ::core::mem::MaybeUninit<#ty> {
766                            // SAFETY:
767                            // We mutably alias the underlying cell, which is not very safe, because
768                            // it could already be borrowed immutably. However, for this particular case
769                            // it is somewhat okay, with emphasis on "somewhat". If this function returns
770                            // a constant, this method is safe, because the stack will be overriden with
771                            // the exact same data.
772                            //
773                            // We shorten the lifetime of the borrowed data.
774                            // The data is not being dropped, and is not accessible
775                            // from anywhere else, so this is safe.:w
776                            unsafe { std::mem::transmute(self.#name.as_ptr().as_mut().unwrap()) }
777                        }
778                    }
779                }
780                (None, false) => {
781                    quote! {
782                        #[allow(clippy::mut_from_ref)]
783                        fn #name(&self) -> &mut ::core::mem::MaybeUninit<#ty> {
784                            // SAFETY:
785                            // We mutably alias the underlying cell, which is not very safe, because
786                            // it could already be borrowed immutably. However, for this particular case
787                            // it is somewhat okay, with emphasis on "somewhat". If this function returns
788                            // a constant, this method is safe, because the stack will be overriden with
789                            // the exact same data.
790                            unsafe { self.#name.as_ptr().as_mut().unwrap() }
791                        }
792                    }
793                }
794            };
795
796            stream.extend(gen);
797        }
798    }
799
800    pub fn vtbl_args(&self) -> TokenStream {
801        let mut ret = TokenStream::new();
802
803        for arg in &self.args {
804            arg.c_args.to_tokens(&mut ret);
805        }
806
807        ret
808    }
809
810    pub fn vtbl_args_cast(&self) -> TokenStream {
811        let mut ret = TokenStream::new();
812
813        for arg in &self.args {
814            arg.c_cast_args.to_tokens(&mut ret);
815        }
816
817        ret
818    }
819
820    pub fn trait_args(&self) -> TokenStream {
821        let mut ret = TokenStream::new();
822
823        for arg in &self.orig_args {
824            let arg = match arg {
825                FnArg::Typed(pat) => {
826                    if let Pat::Ident(PatIdent { ident, .. }) = &*pat.pat {
827                        let ty = &*pat.ty;
828                        // TODO: handle subpat
829                        quote!(#ident: #ty, )
830                    } else {
831                        quote!(#arg, )
832                    }
833                }
834                FnArg::Receiver(rcv) => {
835                    if rcv.reference.is_some() {
836                        quote!(#rcv,)
837                    } else {
838                        quote!(self,)
839                    }
840                }
841            };
842
843            arg.to_tokens(&mut ret);
844        }
845
846        ret
847    }
848
849    pub fn trait_passthrough_args(&self, skip: usize) -> TokenStream {
850        let mut ret = TokenStream::new();
851
852        for arg in self.orig_args.iter().skip(skip) {
853            match arg {
854                FnArg::Typed(ty) => {
855                    let pat = &ty.pat;
856                    quote!(#pat,).to_tokens(&mut ret);
857                }
858                FnArg::Receiver(_) => {
859                    quote!(self,).to_tokens(&mut ret);
860                }
861            }
862        }
863
864        ret
865    }
866
867    pub fn to_c_def_args(&self) -> TokenStream {
868        let mut ret = TokenStream::new();
869
870        for arg in &self.args {
871            arg.to_c_args.to_tokens(&mut ret);
872        }
873
874        ret
875    }
876
877    pub fn to_c_call_args(&self) -> TokenStream {
878        let mut ret = TokenStream::new();
879
880        for arg in &self.args {
881            arg.call_c_args.to_tokens(&mut ret);
882        }
883
884        ret
885    }
886
887    pub fn to_trait_call_args(&self) -> TokenStream {
888        let mut ret = TokenStream::new();
889
890        for arg in &self.args {
891            arg.to_trait_arg.to_tokens(&mut ret);
892        }
893
894        ret
895    }
896
897    /// Create a VTable definition for this function
898    pub fn vtbl_def(&self, stream: &mut TokenStream) {
899        let name = &self.name;
900        let unsafety = &self.get_safety();
901        let extern_abi = self.extern_abi();
902        let args = self.vtbl_args();
903        let ParsedReturnType {
904            c_out,
905            c_cast_out,
906            c_ret_params,
907            lifetime,
908            lifetime_cast,
909            unbounded_hrtb,
910            lifetime_map,
911            ..
912        } = &self.out;
913
914        let ParsedGenerics {
915            life_declare: sig_life_declare,
916            ..
917        } = &self.sig_generics;
918
919        let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
920
921        let (hrtb, args, c_out) = match (
922            lifetime.as_ref().filter(|lt| lt.ident != "cglue_a"),
923            lifetime_cast,
924            *unbounded_hrtb,
925        ) {
926            (_, Some(lifetime), false) => (quote!(#lifetime), self.vtbl_args_cast(), c_cast_out),
927            (Some(lifetime), _, _) => (quote!(#lifetime), args, c_out),
928            _ => (quote!(), args, c_out),
929        };
930
931        let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &parse_quote!(#hrtb));
932
933        let gen = quote! {
934            #name: for<#sig_life_declare> #unsafety extern #extern_abi fn(#args #c_ret_params) #c_out,
935        };
936
937        // ABI-Stable does not support C-unwind ABI, so hack around that.
938        if cfg!(feature = "layout_checks") && self.unwind_safe {
939            let ty = quote!(for<#sig_life_declare> #unsafety extern "C" fn(#args #c_ret_params))
940                .to_string();
941            stream.extend(quote!(#[sabi(unsafe_change_type = #ty)]));
942        }
943
944        stream.extend(gen);
945    }
946
947    /// Create a VTable definition for this function
948    pub fn vtbl_getter_def(&self, stream: &mut TokenStream) {
949        let name = &self.name;
950        let args = self.vtbl_args();
951        let extern_abi = self.extern_abi();
952        let ParsedReturnType {
953            c_out,
954            c_cast_out,
955            c_ret_params,
956            lifetime,
957            lifetime_cast,
958            unbounded_hrtb,
959            lifetime_map,
960            ..
961        } = &self.out;
962
963        let ParsedGenerics {
964            life_declare: sig_life_declare,
965            ..
966        } = &self.sig_generics;
967
968        let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
969
970        let (hrtb, args, c_out) = match (
971            lifetime.as_ref().filter(|lt| lt.ident != "cglue_a"),
972            lifetime_cast,
973            *unbounded_hrtb,
974        ) {
975            (_, Some(lifetime), false) => (quote!(#lifetime), self.vtbl_args_cast(), c_cast_out),
976            (Some(lifetime), _, _) => (quote!(#lifetime), args, c_out),
977            _ => (quote!(), args, c_out),
978        };
979
980        let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &parse_quote!(#hrtb));
981
982        let doc_text = format!(" Getter for {}.", name);
983
984        let gen = quote! {
985            #[doc = #doc_text]
986            ///
987            /// Note that this function is wrapped into unsafe, because if already were is an
988            /// opaque one, it would allow to invoke undefined behaviour.
989            pub fn #name(&self) -> for<#sig_life_declare> unsafe extern #extern_abi fn(#args #c_ret_params) #c_out {
990                unsafe { ::core::mem::transmute(self.#name) }
991            }
992        };
993
994        stream.extend(gen);
995
996        if lifetime_cast.is_some() && *unbounded_hrtb {
997            let name2 = format_ident!("{}_lifetimed", name);
998
999            let safety = self.get_safety();
1000
1001            let args_cast = self.vtbl_args_cast();
1002
1003            let gen = quote! {
1004                #[doc = #doc_text]
1005                ///
1006                /// This function has its argument lifetime cast so that it's usable with anonymous
1007                /// lifetime functions.
1008                ///
1009                /// # Safety
1010                ///
1011                /// This ought to only be used when references to objects are being returned,
1012                /// otherwise there is a risk of lifetime rule breakage.
1013                unsafe fn #name2(&self) -> for<#lifetime_cast> #safety extern #extern_abi fn(#args_cast #c_ret_params) #c_cast_out {
1014                    ::core::mem::transmute(self.#name)
1015                }
1016            };
1017
1018            stream.extend(gen);
1019        }
1020    }
1021
1022    pub fn is_wrapped(&self) -> bool {
1023        true //self.abi == FuncAbi::Wrapped || self.has_nontrivial
1024    }
1025
1026    /// Create a wrapper implementation body for this function
1027    ///
1028    /// If the function is ReprC already, it will not be wrapped and will return `None`
1029    pub fn cfunc_def(
1030        &self,
1031        tokens: &mut TokenStream,
1032        trg_path: &TokenStream,
1033        ret_tmp: &TokenStream,
1034        assocs: &ParsedGenerics,
1035        assoc_equality: &TokenStream,
1036    ) -> Option<&TokenStream> {
1037        if !self.is_wrapped() {
1038            return None;
1039        }
1040
1041        let name = &self.name;
1042        let args = self.vtbl_args();
1043        let extern_abi = self.extern_abi();
1044        let ParsedReturnType {
1045            c_out,
1046            c_where_bounds,
1047            c_where_bounds_cast,
1048            c_ret,
1049            c_pre_call,
1050            c_ret_params,
1051            use_hrtb,
1052            lifetime,
1053            lifetime_cast,
1054            unbounded_hrtb,
1055            lifetime_map,
1056            ..
1057        } = &self.out;
1058        let call_args = self.to_trait_call_args();
1059
1060        let trname = &self.trait_name;
1061        let fnname = format_ident!("{}{}", FN_PREFIX, name);
1062        let safety = self.get_safety();
1063
1064        let ParsedGenerics {
1065            life_declare,
1066            life_use,
1067            gen_declare,
1068            gen_use,
1069            gen_where_bounds,
1070            ..
1071        } = &self.generics;
1072
1073        let assoc_declare = &assocs.gen_declare;
1074
1075        let ParsedGenerics {
1076            life_declare: sig_life_declare,
1077            ..
1078        } = &self.sig_generics;
1079
1080        let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
1081
1082        let tmp_lifetime = if *use_hrtb && !life_use.is_empty() {
1083            quote!('cglue_b, )
1084        } else {
1085            quote!(#life_use)
1086        };
1087
1088        let tmp_lifetime_anon = if *use_hrtb && !life_use.is_empty() {
1089            quote!('_, )
1090        } else {
1091            quote!(#life_use)
1092        };
1093
1094        // Inject 'cglue_a if there are no lifetimes declared by the trait,
1095        // and temp lifetime is needed
1096        let life_declare = if lifetime.is_none() || !life_declare.is_empty() {
1097            life_declare.clone()
1098        } else {
1099            parse_quote!(#lifetime,)
1100        };
1101
1102        let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &life_declare);
1103
1104        let mut container_bound = quote!();
1105
1106        let (c_pre_call, cglue_c_into_inner) = if !recv_reference(&self.receiver) {
1107            container_bound.extend(quote!(#trg_path::CGlueObjBase<Context = CGlueCtx> + ));
1108
1109            (
1110                quote! {
1111                    let (this, cglue_ctx) = cont.cobj_base_owned();
1112                    let this = unsafe { #trg_path::IntoInner::into_inner(this) };
1113                    #c_pre_call
1114                },
1115                Some(quote!(
1116                    CGlueC::InstType: #trg_path::IntoInner<InnerTarget = CGlueC::ObjType>,
1117                )),
1118            )
1119        } else if recv_mutable(&self.receiver) {
1120            let cobj_func = if recv_pin(&self.receiver) {
1121                quote!(cobj_pin_mut)
1122            } else {
1123                quote!(cobj_mut)
1124            };
1125            container_bound.extend(quote!(#trg_path::CGlueObjMut<#ret_tmp, Context = CGlueCtx> + ));
1126            (
1127                quote! {
1128                    let (this, ret_tmp, cglue_ctx) = cont.#cobj_func();
1129                    #c_pre_call
1130                },
1131                None,
1132            )
1133        } else {
1134            let cobj_func = if recv_pin(&self.receiver) {
1135                quote!(cobj_pin_ref)
1136            } else {
1137                quote!(cobj_ref)
1138            };
1139            container_bound.extend(quote!(#trg_path::CGlueObjRef<#ret_tmp, Context = CGlueCtx> + ));
1140            (
1141                quote! {
1142                    let (this, ret_tmp, cglue_ctx) = cont.#cobj_func();
1143                    #c_pre_call
1144                },
1145                None,
1146            )
1147        };
1148
1149        let inner_impl = if let Some(body) = self.custom_conv.c_inner_body.as_ref() {
1150            body.clone()
1151        } else {
1152            quote!(<CGlueC::ObjType as #trname<#tmp_lifetime_anon #gen_use>>::#name(this, #call_args))
1153        };
1154
1155        let c_where_bounds = if lifetime_cast.is_some() && *unbounded_hrtb {
1156            c_where_bounds_cast
1157        } else {
1158            c_where_bounds
1159        };
1160
1161        let ctx_bound = super::traits::ctx_bound();
1162
1163        let gen = quote! {
1164            #safety extern #extern_abi fn #fnname<#sig_life_declare CGlueC: #container_bound, CGlueCtx: #ctx_bound, #gen_declare #assoc_declare>(#args #c_ret_params) #c_out where #gen_where_bounds #c_where_bounds #cglue_c_into_inner CGlueC::ObjType: for<'cglue_b> #trname<#tmp_lifetime #gen_use #assoc_equality>, {
1165                #c_pre_call
1166                let ret = #inner_impl;
1167                #c_ret
1168            }
1169        };
1170
1171        tokens.extend(gen);
1172
1173        Some(c_where_bounds)
1174    }
1175
1176    pub fn vtbl_default_def(&self, tokens: &mut TokenStream) {
1177        let name = &self.name;
1178        let fnname = format_ident!("{}{}", FN_PREFIX, name);
1179        tokens.extend(quote!(#name: #fnname,));
1180    }
1181
1182    pub fn get_safety(&self) -> TokenStream {
1183        if self.safe {
1184            quote!()
1185        } else {
1186            quote!(unsafe)
1187        }
1188    }
1189
1190    pub fn extern_abi(&self) -> TokenStream {
1191        if self.unwind_safe {
1192            quote!("C-unwind")
1193        } else {
1194            quote!("C")
1195        }
1196    }
1197
1198    pub fn trait_impl(&self, tokens: &mut TokenStream) -> (bool, bool, bool) {
1199        if !self.only_c_side {
1200            let name = &self.name;
1201            let args = self.trait_args();
1202            let ParsedReturnType {
1203                ty: out,
1204                impl_func_ret,
1205                c_ret_precall_def,
1206                c_call_ret_args,
1207                lifetime_cast,
1208                unbounded_hrtb,
1209                ..
1210            } = &self.out;
1211            let def_args = self.to_c_def_args();
1212            let call_args = self.to_c_call_args();
1213            let safety = self.get_safety();
1214            let abi = self.abi.prefix();
1215
1216            let ParsedGenerics {
1217                life_declare: sig_life_declare,
1218                gen_declare: sig_gen_declare,
1219                ..
1220            } = &self.sig_generics;
1221
1222            let get_vfunc = if lifetime_cast.is_some() && *unbounded_hrtb {
1223                let name_lifetimed = format_ident!("{}_lifetimed", name);
1224                quote!(unsafe { self.get_vtbl().#name_lifetimed() })
1225            } else {
1226                quote!(self.get_vtbl().#name)
1227            };
1228
1229            let custom_precall_impl = self.custom_conv.pre_call_impl.to_token_stream();
1230
1231            let impl_func_ret = if let Some(impl_func_ret) = &self.custom_conv.impl_func_ret {
1232                impl_func_ret
1233            } else {
1234                impl_func_ret
1235            };
1236
1237            let gen = quote! {
1238                #[inline(always)]
1239                #safety #abi fn #name <#sig_life_declare #sig_gen_declare> (#args) #out {
1240                    let __cglue_vfunc = #get_vfunc;
1241                    #custom_precall_impl
1242                    #def_args
1243                    #c_ret_precall_def
1244                    let mut ret = __cglue_vfunc(#call_args #c_call_ret_args);
1245                    #impl_func_ret
1246                }
1247            };
1248
1249            tokens.extend(gen);
1250        }
1251
1252        (
1253            recv_mutable(&self.receiver),
1254            !recv_reference(&self.receiver),
1255            self.out.return_self,
1256        )
1257    }
1258
1259    pub fn forward_wrapped_trait_impl(&self, tokens: &mut TokenStream) -> bool {
1260        if !recv_reference(&self.receiver) {
1261            return false;
1262        }
1263
1264        let name = &self.name;
1265        let args = self.trait_args();
1266        let passthrough_args = self.trait_passthrough_args(1);
1267        let ParsedReturnType {
1268            ty: out, use_wrap, ..
1269        } = &self.out;
1270        let safety = self.get_safety();
1271        let abi = self.abi.prefix();
1272
1273        let ParsedGenerics {
1274            life_declare,
1275            gen_declare,
1276            ..
1277        } = &self.sig_generics;
1278
1279        let return_out = if *use_wrap {
1280            quote!(Self(ret))
1281        } else {
1282            quote!(ret)
1283        };
1284
1285        let gen = quote! {
1286            #[inline(always)]
1287            #safety #abi fn #name <#life_declare #gen_declare> (#args) #out {
1288                let ret = (self.0).#name(#passthrough_args);
1289                #return_out
1290            }
1291        };
1292
1293        tokens.extend(gen);
1294
1295        recv_mutable(&self.receiver)
1296    }
1297
1298    pub fn arc_wrapped_trait_impl(&self, tokens: &mut TokenStream) {
1299        let name = &self.name;
1300        let args = self.trait_args();
1301        let passthrough_args = self.trait_passthrough_args(1);
1302        let ParsedReturnType {
1303            ty: out, use_wrap, ..
1304        } = &self.out;
1305        let safety = self.get_safety();
1306        let abi = self.abi.prefix();
1307
1308        let ParsedGenerics {
1309            life_declare,
1310            gen_declare,
1311            ..
1312        } = &self.sig_generics;
1313
1314        let get_inner = if !recv_reference(&self.receiver) {
1315            quote!(self.into_inner())
1316        } else if recv_mutable(&self.receiver) {
1317            quote!(self.as_mut())
1318        } else {
1319            quote!(self.as_ref())
1320        };
1321
1322        let return_out = if *use_wrap {
1323            quote!((ret, arc).into())
1324        } else {
1325            quote!(ret)
1326        };
1327
1328        let gen = quote! {
1329            #[inline(always)]
1330            #safety #abi fn #name <#life_declare #gen_declare> (#args) #out {
1331                let (inner, arc) = #get_inner;
1332                let ret = inner.#name(#passthrough_args);
1333                #return_out
1334            }
1335        };
1336
1337        tokens.extend(gen);
1338    }
1339
1340    pub fn int_trait_impl(
1341        &self,
1342        ext_path: Option<&Path>,
1343        ext_name: &Ident,
1344        tokens: &mut TokenStream,
1345    ) {
1346        let name = &self.name;
1347        let args = self.trait_args();
1348        let passthrough_args = self.trait_passthrough_args(0);
1349        let ParsedReturnType { ty: out, .. } = &self.out;
1350        let safety = self.get_safety();
1351        let abi = self.abi.prefix();
1352
1353        let gen = quote! {
1354            #[inline(always)]
1355            #safety #abi fn #name (#args) #out {
1356                #ext_path #ext_name::#name(#passthrough_args)
1357            }
1358        };
1359
1360        tokens.extend(gen);
1361    }
1362}
1363
1364#[derive(Debug, Eq, PartialEq)]
1365enum FuncAbi {
1366    ReprC,
1367    ReprCUnwind,
1368    Wrapped,
1369}
1370
1371impl FuncAbi {
1372    pub fn prefix(&self) -> TokenStream {
1373        match self {
1374            FuncAbi::ReprC => quote!(extern "C"),
1375            FuncAbi::ReprCUnwind => quote!(extern "C-unwind"),
1376            FuncAbi::Wrapped => quote!(),
1377        }
1378    }
1379}
1380
1381impl From<Option<Abi>> for FuncAbi {
1382    fn from(abi: Option<Abi>) -> Self {
1383        // If the function uses C abi, we can omit wrapper functions
1384        if let Some(Abi {
1385            extern_token: _,
1386            name: Some(abi),
1387        }) = abi
1388        {
1389            if abi.value() == "C" {
1390                return FuncAbi::ReprC;
1391            }
1392
1393            if abi.value() == "C-unwind" {
1394                return FuncAbi::ReprCUnwind;
1395            }
1396        }
1397
1398        FuncAbi::Wrapped
1399    }
1400}
1401
1402struct ParsedReturnType {
1403    ty: ReturnType,
1404    c_out: TokenStream,
1405    c_cast_out: TokenStream,
1406    c_where_bounds: TokenStream,
1407    c_where_bounds_cast: TokenStream,
1408    c_ret_params: TokenStream,
1409    c_ret_precall_def: TokenStream,
1410    c_call_ret_args: TokenStream,
1411    c_pre_call: Option<TokenStream>,
1412    c_ret: TokenStream,
1413    impl_func_ret: TokenStream,
1414    /// Whether HRTB and tmp stack should be injected.
1415    ///
1416    /// HRTB is the `for<'cglue_b>` bound to bind `this` lifetime to be the same one as another
1417    /// argument's, as well as the return type's. This is only relevant when tmp_ret is being
1418    /// used. In addition to that, generic bounds will be added to the C wrapper for equivalency.
1419    injected_ret_tmp: Option<GenericType>,
1420    injected_ret_tmp_static: Option<GenericType>,
1421    use_hrtb: bool,
1422    lifetime: Option<Lifetime>,
1423    lifetime_cast: Option<Lifetime>,
1424    unbounded_hrtb: bool,
1425    return_self: bool,
1426    use_wrap: bool,
1427    // Map in-function lifetimes to type lifetimes
1428    lifetime_map: BTreeMap<Lifetime, Lifetime>,
1429}
1430
1431// TODO: handle more cases
1432#[allow(clippy::single_match)]
1433fn wrapped_lifetime(mut ty: Type, target: Lifetime) -> Type {
1434    match &mut ty {
1435        Type::Path(path) => {
1436            for seg in path.path.segments.iter_mut() {
1437                if let PathArguments::AngleBracketed(args) = &mut seg.arguments {
1438                    for arg in args.args.iter_mut() {
1439                        match arg {
1440                            GenericArgument::Lifetime(lt) => {
1441                                if lt.ident != format_ident!("static") {
1442                                    *lt = target.clone()
1443                                }
1444                            }
1445                            GenericArgument::Type(ty) => {
1446                                *ty = wrapped_lifetime(ty.clone(), target.clone())
1447                            }
1448                            _ => {}
1449                        }
1450                    }
1451                }
1452            }
1453        }
1454        _ => {}
1455    }
1456    ty
1457}
1458
1459impl ParsedReturnType {
1460    #[allow(clippy::never_loop)]
1461    fn new(
1462        (ty, c_override): (ReturnType, Option<&ReturnType>),
1463        targets: &BTreeMap<Option<AssocType>, WrappedType>,
1464        res_override: Option<&Ident>,
1465        int_result: bool,
1466        unsafety: &TokenStream,
1467        (func_name, receiver): (&Ident, &FnArg),
1468        (crate_path, trait_name, trait_generics): (&TokenStream, &Ident, &ParsedGenerics),
1469    ) -> Self {
1470        let mut c_ty = c_override.unwrap_or(&ty).clone();
1471
1472        let mut ret = Self {
1473            c_out: ty.to_token_stream(),
1474            c_cast_out: ty.to_token_stream(),
1475            ty,
1476            c_where_bounds: quote!(),
1477            c_where_bounds_cast: quote!(),
1478            c_ret_params: quote!(),
1479            c_ret_precall_def: quote!(),
1480            c_call_ret_args: quote!(),
1481            c_pre_call: None,
1482            c_ret: quote!(ret),
1483            impl_func_ret: quote!(ret),
1484            injected_ret_tmp: None,
1485            injected_ret_tmp_static: None,
1486            use_hrtb: false,
1487            lifetime: None,
1488            lifetime_cast: None,
1489            unbounded_hrtb: false,
1490            return_self: false,
1491            use_wrap: false,
1492            lifetime_map: Default::default(),
1493        };
1494
1495        if let ReturnType::Type(_, ty) = &mut c_ty {
1496            let mut ty_cast = None;
1497
1498            // If this branch is hit (whenever ty includes any of the targets), then return type is
1499            // replaced with c_ty. However, we need to do that regardless in custom impl.
1500            if let Some(wrapped) = ret_wrap_type(&mut *ty, targets) {
1501                let old_ty = wrapped.0;
1502                let trait_ty = wrapped.1;
1503                let WrappedType {
1504                    return_conv,
1505                    lifetime_bound,
1506                    lifetime_type_bound,
1507                    other_bounds,
1508                    other_bounds_simple,
1509                    inject_ret_tmp,
1510                    impl_return_conv,
1511                    ty_static,
1512                    ty_ret_tmp,
1513                    ty:
1514                        GenericType {
1515                            generic_lifetimes: old_lifetimes,
1516                            ..
1517                        },
1518                    ..
1519                } = wrapped.2;
1520
1521                // Swap to check if trait_ty even exists before cloning
1522                ret.lifetime_map = trait_ty
1523                    .iter()
1524                    .flat_map(|assoc| assoc.generics.lifetimes().map(|v| &v.lifetime).cloned())
1525                    .zip(old_lifetimes.iter().cloned())
1526                    .collect();
1527
1528                // TODO: sort out the order
1529
1530                let (mutable, lifetime) = match (inject_ret_tmp, &**ty) {
1531                    (true, Type::Reference(ty)) => {
1532                        (ty.mutability.is_some(), ty.lifetime.as_ref().cloned())
1533                    }
1534                    (false, _) => (false, None),
1535                    _ => {
1536                        panic!(
1537                            "Wrapped ref return currently only valid for references! (ty: {ty})",
1538                            ty = ty.to_token_stream()
1539                        )
1540                    }
1541                };
1542
1543                let unbounded_hrtb = lifetime.is_none() && lifetime_type_bound.is_none();
1544
1545                let cglue_b_lifetime = Lifetime {
1546                    apostrophe: proc_macro2::Span::call_site(),
1547                    ident: format_ident!("cglue_b"),
1548                };
1549
1550                let lifetime = lifetime.or_else(|| lifetime_bound.clone()).or_else(|| {
1551                    Some(Lifetime {
1552                        apostrophe: proc_macro2::Span::call_site(),
1553                        ident: format_ident!("cglue_a"),
1554                    })
1555                });
1556
1557                let lifetime_cast = if lifetime
1558                    .as_ref()
1559                    .filter(|lt| lt.ident == "cglue_a")
1560                    .is_some()
1561                {
1562                    ty_cast = Some(ty.clone());
1563                    Some(cglue_b_lifetime.clone())
1564                } else {
1565                    None
1566                };
1567
1568                if let Some(lifetime) = &lifetime {
1569                    **ty = wrapped_lifetime(*ty.clone(), lifetime.clone());
1570                }
1571
1572                // TODO: should this inherit lifetime, or just fallback on lifetime?
1573                let lifetime_type_bound = lifetime_type_bound.clone().map(|lt| {
1574                    if lt.ident != "static" {
1575                        cglue_b_lifetime
1576                    } else {
1577                        lt
1578                    }
1579                });
1580
1581                let ret_wrap = match return_conv {
1582                    Some(conv) => quote! {
1583                        let mut conv = #conv;
1584                        conv(ret)
1585                    },
1586                    _ => quote!(ret.into()),
1587                };
1588
1589                let life_use = &trait_generics.life_use;
1590                let gen_use = &trait_generics.gen_use;
1591
1592                // TODO: where do we need this bound?
1593
1594                let is_static = lifetime_type_bound.map(|l| l.ident == "static") == Some(true);
1595
1596                let (static_bound, static_bound_simple) = if is_static && trait_ty.is_some() {
1597                    if life_use.is_empty() {
1598                        (
1599                            quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<#gen_use>>::#trait_ty: 'static,),
1600                            quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<#gen_use>>::#trait_ty: 'static,),
1601                        )
1602                    } else {
1603                        (
1604                            quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<'cglue_b, #gen_use>>::#trait_ty: 'static,),
1605                            quote!(<CGlueC::ObjType as #trait_name<'cglue_a, #gen_use>>::#trait_ty: 'static,),
1606                        )
1607                    }
1608                } else {
1609                    (quote!(), quote!())
1610                };
1611
1612                let where_bound = quote!(#static_bound #other_bounds);
1613                let where_bound_simple = quote!(#static_bound_simple #other_bounds_simple);
1614
1615                // Replace the lifetime of the type.
1616                if let (true, Type::Reference(ty)) = (inject_ret_tmp, &mut **ty) {
1617                    ty.lifetime = lifetime.clone();
1618
1619                    if let Some(ty_cast) = &mut ty_cast {
1620                        if let Type::Reference(ty_cast) = &mut **ty_cast {
1621                            ty_cast.lifetime = lifetime_cast.clone();
1622                        }
1623                    }
1624                };
1625
1626                let (injected_ret_tmp, c_pre_call) = match (inject_ret_tmp, mutable) {
1627                    (true, false) => (
1628                        ty_ret_tmp.clone(),
1629                        quote!(let ret_tmp = ret_tmp.#func_name();),
1630                    ),
1631                    (true, true) => (
1632                        ty_ret_tmp.clone(),
1633                        quote!(let ret_tmp = ret_tmp.#func_name();),
1634                    ),
1635                    _ => (None, quote!()),
1636                };
1637
1638                let c_pre_call = if recv_reference(receiver) {
1639                    quote!(#c_pre_call let cglue_ctx = cglue_ctx.clone();)
1640                } else {
1641                    c_pre_call
1642                };
1643
1644                let impl_return_conv = impl_return_conv
1645                    .as_ref()
1646                    .cloned()
1647                    .unwrap_or_else(|| quote!(ret));
1648
1649                let return_self = trait_ty.map(|i| i.ident == "Self") == Some(true);
1650
1651                ret.c_out = quote!(-> #ty);
1652                ret.c_cast_out = quote!(-> #ty_cast);
1653
1654                // If we are returning self, do not actually change the return type.
1655                // I know, messy :(
1656                if return_self {
1657                    *ty = Box::new(old_ty);
1658                }
1659
1660                ret.c_where_bounds = where_bound;
1661                ret.c_where_bounds_cast = where_bound_simple;
1662                ret.c_ret_params = quote!();
1663                ret.c_ret_precall_def = quote!();
1664                ret.c_call_ret_args = quote!();
1665                ret.c_pre_call = Some(c_pre_call);
1666                ret.c_ret = quote!(#ret_wrap);
1667                ret.impl_func_ret = impl_return_conv;
1668                ret.injected_ret_tmp = injected_ret_tmp;
1669                ret.injected_ret_tmp_static = ty_static.clone();
1670                ret.use_hrtb = true;
1671                ret.unbounded_hrtb = unbounded_hrtb;
1672                ret.return_self = return_self;
1673                ret.use_wrap = true;
1674                ret.lifetime = lifetime;
1675                ret.lifetime_cast = lifetime_cast;
1676            } else {
1677                ret.c_out = quote!(-> #ty);
1678            }
1679
1680            match &mut **ty {
1681                Type::Reference(r) => {
1682                    let is_mut = r.mutability.is_some();
1683
1684                    let mut new_tys = vec![];
1685
1686                    let default_lt = Lifetime {
1687                        apostrophe: proc_macro2::Span::call_site(),
1688                        ident: format_ident!("_"),
1689                    };
1690
1691                    for r in Some(&*r)
1692                        .into_iter()
1693                        .chain(ty_cast.as_deref().into_iter().filter_map(|r| {
1694                            if let Type::Reference(r) = r {
1695                                Some(r)
1696                            } else {
1697                                None
1698                            }
1699                        }))
1700                    {
1701                        let lt = r.lifetime.as_ref().unwrap_or(&default_lt);
1702
1703                        new_tys.push(match &*r.elem {
1704                            Type::Slice(s) => {
1705                                let ty = &*s.elem;
1706                                Some(if is_mut {
1707                                    quote!(#crate_path::slice::CSliceMut<#lt, #ty>)
1708                                } else {
1709                                    quote!(#crate_path::slice::CSliceRef<#lt, #ty>)
1710                                })
1711                                .map(|v| (v, false))
1712                            }
1713                            Type::Path(p) => if let Some("str") =
1714                                p.path.get_ident().map(|i| i.to_string()).as_deref()
1715                            {
1716                                Some(if is_mut {
1717                                    quote!(#crate_path::slice::CSliceMut<#lt, u8>)
1718                                } else {
1719                                    quote!(#crate_path::slice::CSliceRef<#lt, u8>)
1720                                })
1721                            } else {
1722                                None
1723                            }
1724                            .map(|v| (v, true)),
1725                            _ => None,
1726                        });
1727                    }
1728
1729                    if let Some((slty, into_str)) = &new_tys[0] {
1730                        ret.c_out = quote!(-> #slty);
1731                        if let Some(sltyc) = new_tys.get(1) {
1732                            let sltyc = sltyc.as_ref().map(|(v, _)| v);
1733                            ret.c_cast_out = quote!(-> #sltyc);
1734                        }
1735                        ret.c_ret.extend(quote!(.into()));
1736                        if *into_str {
1737                            let old_ret = ret.impl_func_ret;
1738                            ret.impl_func_ret = quote! {
1739                                unsafe { #old_ret .into_str() }
1740                            }
1741                        } else {
1742                            ret.impl_func_ret.extend(quote!(.into()));
1743                        }
1744                    }
1745                }
1746                Type::Path(p) => {
1747                    let last = p.path.segments.last();
1748                    if let Some((PathArguments::AngleBracketed(args), last)) =
1749                        last.map(|l| (&l.arguments, l))
1750                    {
1751                        let ident = &last.ident;
1752
1753                        let result_ident = format_ident!("Result");
1754
1755                        let result_ident = res_override.unwrap_or(&result_ident);
1756
1757                        match ident.to_string().as_str() {
1758                            "Option" => {
1759                                if let Some(GenericArgument::Type(a)) = args.args.first() {
1760                                    if !crate::util::is_null_pointer_optimizable(a, &[]) {
1761                                        let new_path: Path =
1762                                            parse2(quote!(#crate_path::option::COption))
1763                                                .expect("Failed to parse COption path");
1764
1765                                        replace_path_keep_final_args(
1766                                            Some(&mut **ty),
1767                                            new_path.clone(),
1768                                        );
1769                                        replace_path_keep_final_args(
1770                                            ty_cast.as_deref_mut(),
1771                                            new_path,
1772                                        );
1773
1774                                        ret.c_out = quote!(-> #ty);
1775                                        ret.c_cast_out = quote!(-> #ty_cast);
1776                                        ret.c_ret.extend(quote!(.into()));
1777                                        ret.impl_func_ret.extend(quote!(.into()));
1778                                    }
1779                                }
1780                            }
1781                            _ => {
1782                                if ident == result_ident {
1783                                    let mut args = args.args.iter();
1784
1785                                    let to_match =
1786                                        (args.next(), args.next(), args.next(), int_result);
1787
1788                                    std::mem::drop(args);
1789
1790                                    match to_match {
1791                                        (Some(GenericArgument::Type(a)), _, None, true) => loop {
1792                                            ret.c_out = quote!(-> i32);
1793                                            ret.c_cast_out = quote!(-> i32);
1794
1795                                            let c_ret = &ret.c_ret;
1796
1797                                            let mapped_ret = quote! {
1798                                                let ret = ret.map(|ret| {
1799                                                    #c_ret
1800                                                });
1801                                            };
1802
1803                                            if let Type::Tuple(tup) = a {
1804                                                if tup.elems.is_empty() {
1805                                                    ret.c_ret = quote! {
1806                                                        #mapped_ret
1807                                                        #crate_path::result::into_int_result(ret)
1808                                                    };
1809                                                    let impl_func_ret = &ret.impl_func_ret;
1810                                                    ret.impl_func_ret = quote!(#crate_path::result::from_int_result_empty(#impl_func_ret));
1811
1812                                                    break;
1813                                                }
1814                                            }
1815
1816                                            ret.c_ret_params.extend(
1817                                                quote!(ok_out: &mut ::core::mem::MaybeUninit<#a>,),
1818                                            );
1819                                            ret.c_ret_precall_def.extend(quote!(let mut ok_out = ::core::mem::MaybeUninit::uninit();));
1820                                            ret.c_call_ret_args.extend(quote!(&mut ok_out,));
1821
1822                                            ret.c_ret = quote! {
1823                                                #mapped_ret
1824                                                #crate_path::result::into_int_out_result(ret, ok_out)
1825                                            };
1826                                            let impl_func_ret = &ret.impl_func_ret;
1827                                            ret.impl_func_ret = quote!(#unsafety { #crate_path::result::from_int_result(#impl_func_ret, ok_out) });
1828
1829                                            break;
1830                                        },
1831                                        (
1832                                            Some(GenericArgument::Type(_)),
1833                                            Some(GenericArgument::Type(_)),
1834                                            None,
1835                                            _,
1836                                        ) => {
1837                                            let new_path: Path =
1838                                                parse2(quote!(#crate_path::result::CResult))
1839                                                    .expect("Failed to parse CResult path");
1840
1841                                            replace_path_keep_final_args(
1842                                                Some(&mut **ty),
1843                                                new_path.clone(),
1844                                            );
1845                                            replace_path_keep_final_args(
1846                                                ty_cast.as_deref_mut(),
1847                                                new_path,
1848                                            );
1849
1850                                            ret.c_out = quote!(-> #ty);
1851                                            ret.c_cast_out = quote!(-> #ty_cast);
1852
1853                                            let c_ret = &ret.c_ret;
1854
1855                                            let mapped_ret = quote! {
1856                                                let ret = ret.map(|ret| {
1857                                                    #c_ret
1858                                                });
1859                                            };
1860
1861                                            ret.c_ret = quote! {
1862                                                #mapped_ret
1863                                                ret.into()
1864                                            };
1865
1866                                            ret.impl_func_ret.extend(quote!(.into()));
1867                                        }
1868                                        _ => {}
1869                                    };
1870                                }
1871                            }
1872                        }
1873                    }
1874                }
1875                _ => {}
1876            }
1877        }
1878
1879        ret
1880    }
1881}
1882
1883fn replace_path_keep_final_args(ty: Option<&mut Type>, new_path: Path) {
1884    if let Some(Type::Path(path)) = ty {
1885        let old_path = std::mem::replace(&mut path.path, new_path);
1886        if let Some(seg) = old_path.segments.into_iter().last() {
1887            if let Some(new_seg) = path.path.segments.iter_mut().last() {
1888                new_seg.arguments = seg.arguments;
1889            }
1890        }
1891    }
1892}