@@ -741,15 +741,15 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
741
741
#trampolines
742
742
#dispatch
743
743
} ) ;
744
- match & efn. receiver {
745
- None => {
744
+ match ( & efn. receiver , & efn . self_type ) {
745
+ ( None , None ) => {
746
746
quote ! {
747
747
#doc
748
748
#attrs
749
749
#visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
750
750
}
751
751
}
752
- Some ( receiver) => {
752
+ ( Some ( receiver) , None ) => {
753
753
let elided_generics;
754
754
let receiver_ident = & receiver. ty . rust ;
755
755
let resolve = types. resolve ( & receiver. ty ) ;
@@ -781,6 +781,39 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
781
781
}
782
782
}
783
783
}
784
+ ( None , Some ( self_type) ) => {
785
+ let elided_generics;
786
+ let resolve = types. resolve ( self_type) ;
787
+ let self_type_ident = & resolve. name . rust ;
788
+ let self_type_generics = if resolve. generics . lt_token . is_some ( ) {
789
+ & resolve. generics
790
+ } else {
791
+ elided_generics = Lifetimes {
792
+ lt_token : resolve. generics . lt_token ,
793
+ lifetimes : resolve
794
+ . generics
795
+ . lifetimes
796
+ . pairs ( )
797
+ . map ( |pair| {
798
+ let lifetime = Lifetime :: new ( "'_" , pair. value ( ) . apostrophe ) ;
799
+ let punct = pair. punct ( ) . map ( |& & comma| comma) ;
800
+ punctuated:: Pair :: new ( lifetime, punct)
801
+ } )
802
+ . collect ( ) ,
803
+ gt_token : resolve. generics . gt_token ,
804
+ } ;
805
+ & elided_generics
806
+ } ;
807
+ quote_spanned ! { ident. span( ) =>
808
+ #[ automatically_derived]
809
+ impl #generics #self_type_ident #self_type_generics {
810
+ #doc
811
+ #attrs
812
+ #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
813
+ }
814
+ }
815
+ }
816
+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
784
817
}
785
818
}
786
819
@@ -797,6 +830,7 @@ fn expand_function_pointer_trampoline(
797
830
let body_span = efn. semi_token . span ;
798
831
let shim = expand_rust_function_shim_impl (
799
832
sig,
833
+ & efn. self_type ,
800
834
types,
801
835
& r_trampoline,
802
836
local_name,
@@ -940,18 +974,33 @@ fn expand_forbid(impls: TokenStream) -> TokenStream {
940
974
941
975
fn expand_rust_function_shim ( efn : & ExternFn , types : & Types ) -> TokenStream {
942
976
let link_name = mangle:: extern_fn ( efn, types) ;
943
- let local_name = match & efn. receiver {
944
- None => format_ident ! ( "__{}" , efn. name. rust) ,
945
- Some ( receiver) => format_ident ! ( "__{}__{}" , receiver. ty. rust, efn. name. rust) ,
977
+ let local_name = match ( & efn. receiver , & efn. self_type ) {
978
+ ( None , None ) => format_ident ! ( "__{}" , efn. name. rust) ,
979
+ ( Some ( receiver) , None ) => format_ident ! ( "__{}__{}" , receiver. ty. rust, efn. name. rust) ,
980
+ ( None , Some ( self_type) ) => format_ident ! (
981
+ "__{}__{}" ,
982
+ types. resolve( self_type) . name. rust,
983
+ efn. name. rust
984
+ ) ,
985
+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
946
986
} ;
947
- let prevent_unwind_label = match & efn. receiver {
948
- None => format ! ( "::{}" , efn. name. rust) ,
949
- Some ( receiver) => format ! ( "::{}::{}" , receiver. ty. rust, efn. name. rust) ,
987
+ let prevent_unwind_label = match ( & efn. receiver , & efn. self_type ) {
988
+ ( None , None ) => format ! ( "::{}" , efn. name. rust) ,
989
+ ( Some ( receiver) , None ) => format ! ( "::{}::{}" , receiver. ty. rust, efn. name. rust) ,
990
+ ( None , Some ( self_type) ) => {
991
+ format ! (
992
+ "::{}::{}" ,
993
+ types. resolve( self_type) . name. rust,
994
+ efn. name. rust
995
+ )
996
+ }
997
+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
950
998
} ;
951
999
let invoke = Some ( & efn. name . rust ) ;
952
1000
let body_span = efn. semi_token . span ;
953
1001
expand_rust_function_shim_impl (
954
1002
efn,
1003
+ & efn. self_type ,
955
1004
types,
956
1005
& link_name,
957
1006
local_name,
@@ -965,6 +1014,7 @@ fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
965
1014
966
1015
fn expand_rust_function_shim_impl (
967
1016
sig : & Signature ,
1017
+ self_type : & Option < Ident > ,
968
1018
types : & Types ,
969
1019
link_name : & Symbol ,
970
1020
local_name : Ident ,
@@ -1057,7 +1107,8 @@ fn expand_rust_function_shim_impl(
1057
1107
} ) ;
1058
1108
let vars: Vec < _ > = receiver_var. into_iter ( ) . chain ( arg_vars) . collect ( ) ;
1059
1109
1060
- let wrap_super = invoke. map ( |invoke| expand_rust_function_shim_super ( sig, & local_name, invoke) ) ;
1110
+ let wrap_super = invoke
1111
+ . map ( |invoke| expand_rust_function_shim_super ( sig, self_type, types, & local_name, invoke) ) ;
1061
1112
1062
1113
let mut requires_closure;
1063
1114
let mut call = match invoke {
@@ -1182,6 +1233,8 @@ fn expand_rust_function_shim_impl(
1182
1233
// accurate unsafety declaration and no problematic elided lifetimes.
1183
1234
fn expand_rust_function_shim_super (
1184
1235
sig : & Signature ,
1236
+ self_type : & Option < Ident > ,
1237
+ types : & Types ,
1185
1238
local_name : & Ident ,
1186
1239
invoke : & Ident ,
1187
1240
) -> TokenStream {
@@ -1222,12 +1275,17 @@ fn expand_rust_function_shim_super(
1222
1275
let vars = receiver_var. iter ( ) . chain ( arg_vars) ;
1223
1276
1224
1277
let span = invoke. span ( ) ;
1225
- let call = match & sig. receiver {
1226
- None => quote_spanned ! ( span=> super :: #invoke) ,
1227
- Some ( receiver) => {
1278
+ let call = match ( & sig. receiver , & self_type ) {
1279
+ ( None , None ) => quote_spanned ! ( span=> super :: #invoke) ,
1280
+ ( Some ( receiver) , None ) => {
1228
1281
let receiver_type = & receiver. ty . rust ;
1229
1282
quote_spanned ! ( span=> #receiver_type:: #invoke)
1230
1283
}
1284
+ ( None , Some ( self_type) ) => {
1285
+ let self_type = & types. resolve ( self_type) . name . rust ;
1286
+ quote_spanned ! ( span=> #self_type:: #invoke)
1287
+ }
1288
+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
1231
1289
} ;
1232
1290
1233
1291
let mut body = quote_spanned ! ( span=> #call( #( #vars, ) * ) ) ;
0 commit comments