@@ -563,14 +563,10 @@ fn expand_rust_function_shim_impl(
563
563
} ) ;
564
564
let vars = receiver_var. into_iter ( ) . chain ( arg_vars) ;
565
565
566
+ let wrap_super = invoke. map ( |invoke| expand_rust_function_shim_super ( sig, & local_name, invoke) ) ;
567
+
566
568
let mut call = match invoke {
567
- Some ( ident) => match & sig. receiver {
568
- None => quote ! ( super :: #ident) ,
569
- Some ( receiver) => {
570
- let receiver_type = & receiver. ty ;
571
- quote ! ( #receiver_type:: #ident)
572
- }
573
- } ,
569
+ Some ( _) => quote ! ( #local_name) ,
574
570
None => quote ! ( :: std:: mem:: transmute:: <* const ( ) , #sig>( __extern) ) ,
575
571
} ;
576
572
call. extend ( quote ! { ( #( #vars) , * ) } ) ;
@@ -648,11 +644,61 @@ fn expand_rust_function_shim_impl(
648
644
#[ export_name = #link_name]
649
645
unsafe extern "C" fn #local_name( #( #all_args, ) * #outparam #pointer) #ret {
650
646
let __fn = concat!( module_path!( ) , #catch_unwind_label) ;
647
+ #wrap_super
651
648
#expr
652
649
}
653
650
}
654
651
}
655
652
653
+ // A wrapper like `fn f(x: Arg) { super::f(x) }` just to ensure we have the
654
+ // accurate unsafety declaration and no problematic elided lifetimes.
655
+ fn expand_rust_function_shim_super (
656
+ sig : & Signature ,
657
+ local_name : & Ident ,
658
+ invoke : & Ident ,
659
+ ) -> TokenStream {
660
+ let unsafety = sig. unsafety ;
661
+
662
+ let receiver_var = sig
663
+ . receiver
664
+ . as_ref ( )
665
+ . map ( |receiver| Ident :: new ( "__self" , receiver. var . span ) ) ;
666
+ let receiver = sig. receiver . iter ( ) . map ( |receiver| {
667
+ let receiver_type = receiver. ty ( ) ;
668
+ quote ! ( #receiver_var: #receiver_type)
669
+ } ) ;
670
+ let args = sig. args . iter ( ) . map ( |arg| quote ! ( #arg) ) ;
671
+ let all_args = receiver. chain ( args) ;
672
+
673
+ let ret = if sig. throws {
674
+ let ok = match & sig. ret {
675
+ Some ( ret) => quote ! ( #ret) ,
676
+ None => quote ! ( ( ) ) ,
677
+ } ;
678
+ quote ! ( -> :: std:: result:: Result <#ok, impl :: std:: fmt:: Display >)
679
+ } else {
680
+ expand_return_type ( & sig. ret )
681
+ } ;
682
+
683
+ let arg_vars = sig. args . iter ( ) . map ( |arg| & arg. ident ) ;
684
+ let vars = receiver_var. iter ( ) . chain ( arg_vars) ;
685
+
686
+ let span = invoke. span ( ) ;
687
+ let call = match & sig. receiver {
688
+ None => quote_spanned ! ( span=> super :: #invoke) ,
689
+ Some ( receiver) => {
690
+ let receiver_type = & receiver. ty ;
691
+ quote_spanned ! ( span=> #receiver_type:: #invoke)
692
+ }
693
+ } ;
694
+
695
+ quote_spanned ! { span=>
696
+ #unsafety fn #local_name( #( #all_args, ) * ) #ret {
697
+ #call( #( #vars, ) * )
698
+ }
699
+ }
700
+ }
701
+
656
702
fn expand_type_alias ( alias : & TypeAlias ) -> TokenStream {
657
703
let doc = & alias. doc ;
658
704
let ident = & alias. name . rust ;
0 commit comments