@@ -271,16 +271,29 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
271
271
272
272
out. next_section ( ) ;
273
273
274
+ // default move/copy constructors/assignments for trivially copyable types
275
+ // used for indirect return
276
+ if out. types . structs_with_constructors . contains ( & strct. name . rust ) {
277
+ writeln ! ( out, " {0}() noexcept = default;" , strct. name. cxx) ;
278
+ writeln ! ( out, " {0}(const {0}&) noexcept = default;" , strct. name. cxx) ;
279
+ writeln ! ( out, " {0}({0}&&) noexcept = default;" , strct. name. cxx) ;
280
+ writeln ! ( out, " {0}& operator=(const {0}&) noexcept = default;" , strct. name. cxx) ;
281
+ writeln ! ( out, " {0}& operator=({0}&&) noexcept = default;" , strct. name. cxx) ;
282
+ }
283
+
274
284
for method in methods {
275
285
if !method. doc . is_empty ( ) {
276
286
out. next_section ( ) ;
277
287
}
278
288
write_doc ( out, " " , & method. doc ) ;
279
289
write ! ( out, " " ) ;
280
290
let sig = & method. sig ;
281
- let local_name = method. name . cxx . to_string ( ) ;
291
+ let local_name = match ( & method. self_type , sig. constructor ) {
292
+ ( Some ( self_type) , true ) => out. types . resolve ( self_type) . name . cxx . to_string ( ) ,
293
+ _ => method. name . cxx . to_string ( ) ,
294
+ } ;
282
295
let indirect_call = false ;
283
- if method. self_type . is_some ( ) {
296
+ if method. self_type . is_some ( ) && !method . sig . constructor {
284
297
write ! ( out, "static " ) ;
285
298
}
286
299
write_rust_function_shim_decl ( out, & local_name, sig, & None , indirect_call) ;
@@ -375,7 +388,7 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
375
388
let sig = & method. sig ;
376
389
let local_name = method. name . cxx . to_string ( ) ;
377
390
let indirect_call = false ;
378
- if method. self_type . is_some ( ) {
391
+ if method. self_type . is_some ( ) && !method . sig . constructor {
379
392
write ! ( out, "static " ) ;
380
393
}
381
394
write_rust_function_shim_decl ( out, & local_name, sig, & None , indirect_call) ;
@@ -754,51 +767,61 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
754
767
if !efn. args . is_empty ( ) || efn. receiver . is_some ( ) {
755
768
write ! ( out, ", " ) ;
756
769
}
757
- write_indirect_return_type_space ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
770
+ if efn. sig . constructor {
771
+ write ! (
772
+ out,
773
+ "{} " ,
774
+ out. types. resolve( efn. self_type. as_ref( ) . unwrap( ) ) . name. cxx
775
+ ) ;
776
+ } else {
777
+ write_indirect_return_type_space ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
778
+ }
758
779
write ! ( out, "*return$" ) ;
759
780
}
760
781
writeln ! ( out, ") noexcept {{" ) ;
761
- write ! ( out, " " ) ;
762
- write_return_type ( out, & efn. ret ) ;
763
- match & efn. receiver {
764
- None => write ! ( out, "(*{}$)(" , efn. name. rust) ,
765
- Some ( receiver) => write ! (
766
- out,
767
- "({}::*{}$)(" ,
768
- out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
769
- efn. name. rust,
770
- ) ,
771
- }
772
- for ( i, arg) in efn. args . iter ( ) . enumerate ( ) {
773
- if i > 0 {
774
- write ! ( out, ", " ) ;
782
+ if !efn. sig . constructor {
783
+ write ! ( out, " " ) ;
784
+ write_return_type ( out, & efn. ret ) ;
785
+ match & efn. receiver {
786
+ None => write ! ( out, "(*{}$)(" , efn. name. rust) ,
787
+ Some ( receiver) => write ! (
788
+ out,
789
+ "({}::*{}$)(" ,
790
+ out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
791
+ efn. name. rust,
792
+ ) ,
775
793
}
776
- write_type ( out, & arg. ty ) ;
777
- }
778
- write ! ( out, ")" ) ;
779
- if let Some ( receiver) = & efn. receiver {
780
- if !receiver. mutable {
781
- write ! ( out, " const" ) ;
794
+ for ( i, arg) in efn. args . iter ( ) . enumerate ( ) {
795
+ if i > 0 {
796
+ write ! ( out, ", " ) ;
797
+ }
798
+ write_type ( out, & arg. ty ) ;
782
799
}
800
+ write ! ( out, ")" ) ;
801
+ if let Some ( receiver) = & efn. receiver {
802
+ if !receiver. mutable {
803
+ write ! ( out, " const" ) ;
804
+ }
805
+ }
806
+ write ! ( out, " = " ) ;
807
+ match ( & efn. receiver , & efn. self_type ) {
808
+ ( None , None ) => write ! ( out, "{}" , efn. name. to_fully_qualified( ) ) ,
809
+ ( Some ( receiver) , None ) => write ! (
810
+ out,
811
+ "&{}::{}" ,
812
+ out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
813
+ efn. name. cxx,
814
+ ) ,
815
+ ( None , Some ( self_type) ) => write ! (
816
+ out,
817
+ "&{}::{}" ,
818
+ out. types. resolve( self_type) . name. to_fully_qualified( ) ,
819
+ efn. name. cxx,
820
+ ) ,
821
+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
822
+ }
823
+ writeln ! ( out, ";" ) ;
783
824
}
784
- write ! ( out, " = " ) ;
785
- match ( & efn. receiver , & efn. self_type ) {
786
- ( None , None ) => write ! ( out, "{}" , efn. name. to_fully_qualified( ) ) ,
787
- ( Some ( receiver) , None ) => write ! (
788
- out,
789
- "&{}::{}" ,
790
- out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
791
- efn. name. cxx,
792
- ) ,
793
- ( None , Some ( self_type) ) => write ! (
794
- out,
795
- "&{}::{}" ,
796
- out. types. resolve( self_type) . name. to_fully_qualified( ) ,
797
- efn. name. cxx,
798
- ) ,
799
- _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
800
- }
801
- writeln ! ( out, ";" ) ;
802
825
write ! ( out, " " ) ;
803
826
if efn. throws {
804
827
out. builtin . ptr_len = true ;
@@ -811,28 +834,38 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
811
834
if indirect_return {
812
835
out. include . new = true ;
813
836
write ! ( out, "new (return$) " ) ;
814
- write_indirect_return_type ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
837
+ if efn. sig . constructor {
838
+ write ! (
839
+ out,
840
+ "{}" ,
841
+ out. types. resolve( efn. self_type. as_ref( ) . unwrap( ) ) . name. cxx
842
+ ) ;
843
+ } else {
844
+ write_indirect_return_type ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
845
+ }
815
846
write ! ( out, "(" ) ;
816
847
} else if efn. ret . is_some ( ) {
817
848
write ! ( out, "return " ) ;
818
849
}
819
- match & efn. ret {
820
- Some ( Type :: Ref ( _) ) => write ! ( out, "&" ) ,
821
- Some ( Type :: Str ( _) ) if !indirect_return => {
822
- out. builtin . rust_str_repr = true ;
823
- write ! ( out, "::rust::impl<::rust::Str>::repr(" ) ;
850
+ if !efn. sig . constructor {
851
+ match & efn. ret {
852
+ Some ( Type :: Ref ( _) ) => write ! ( out, "&" ) ,
853
+ Some ( Type :: Str ( _) ) if !indirect_return => {
854
+ out. builtin . rust_str_repr = true ;
855
+ write ! ( out, "::rust::impl<::rust::Str>::repr(" ) ;
856
+ }
857
+ Some ( ty @ Type :: SliceRef ( _) ) if !indirect_return => {
858
+ out. builtin . rust_slice_repr = true ;
859
+ write ! ( out, "::rust::impl<" ) ;
860
+ write_type ( out, ty) ;
861
+ write ! ( out, ">::repr(" ) ;
862
+ }
863
+ _ => { }
824
864
}
825
- Some ( ty @ Type :: SliceRef ( _) ) if !indirect_return => {
826
- out. builtin . rust_slice_repr = true ;
827
- write ! ( out, "::rust::impl<" ) ;
828
- write_type ( out, ty) ;
829
- write ! ( out, ">::repr(" ) ;
865
+ match & efn. receiver {
866
+ None => write ! ( out, "{}$(" , efn. name. rust) ,
867
+ Some ( _) => write ! ( out, "(self.*{}$)(" , efn. name. rust) ,
830
868
}
831
- _ => { }
832
- }
833
- match & efn. receiver {
834
- None => write ! ( out, "{}$(" , efn. name. rust) ,
835
- Some ( _) => write ! ( out, "(self.*{}$)(" , efn. name. rust) ,
836
869
}
837
870
for ( i, arg) in efn. args . iter ( ) . enumerate ( ) {
838
871
if i > 0 {
@@ -862,7 +895,9 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
862
895
write ! ( out, "{}" , arg. name. cxx) ;
863
896
}
864
897
}
865
- write ! ( out, ")" ) ;
898
+ if !efn. sig . constructor {
899
+ write ! ( out, ")" ) ;
900
+ }
866
901
match & efn. ret {
867
902
Some ( Type :: RustBox ( _) ) => write ! ( out, ".into_raw()" ) ,
868
903
Some ( Type :: UniquePtr ( _) ) => write ! ( out, ".release()" ) ,
@@ -892,27 +927,36 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
892
927
fn write_function_pointer_trampoline ( out : & mut OutFile , efn : & ExternFn , var : & Pair , f : & Signature ) {
893
928
let r_trampoline = mangle:: r_trampoline ( efn, var, out. types ) ;
894
929
let indirect_call = true ;
895
- write_rust_function_decl_impl ( out, & r_trampoline, f, indirect_call) ;
930
+ write_rust_function_decl_impl ( out, & r_trampoline, f, & efn . self_type , indirect_call) ;
896
931
897
932
out. next_section ( ) ;
898
933
let c_trampoline = mangle:: c_trampoline ( efn, var, out. types ) . to_string ( ) ;
899
934
let doc = Doc :: new ( ) ;
900
- write_rust_function_shim_impl ( out, & c_trampoline, f, & efn. self_type , & doc, & r_trampoline, indirect_call) ;
935
+ write_rust_function_shim_impl (
936
+ out,
937
+ & c_trampoline,
938
+ f,
939
+ & efn. self_type ,
940
+ & doc,
941
+ & r_trampoline,
942
+ indirect_call,
943
+ ) ;
901
944
}
902
945
903
946
fn write_rust_function_decl < ' a > ( out : & mut OutFile < ' a > , efn : & ' a ExternFn ) {
904
947
out. set_namespace ( & efn. name . namespace ) ;
905
948
out. begin_block ( Block :: ExternC ) ;
906
949
let link_name = mangle:: extern_fn ( efn, out. types ) ;
907
950
let indirect_call = false ;
908
- write_rust_function_decl_impl ( out, & link_name, efn, indirect_call) ;
951
+ write_rust_function_decl_impl ( out, & link_name, efn, & efn . self_type , indirect_call) ;
909
952
out. end_block ( Block :: ExternC ) ;
910
953
}
911
954
912
955
fn write_rust_function_decl_impl (
913
956
out : & mut OutFile ,
914
957
link_name : & Symbol ,
915
958
sig : & Signature ,
959
+ self_type : & Option < Ident > ,
916
960
indirect_call : bool ,
917
961
) {
918
962
out. next_section ( ) ;
@@ -947,15 +991,23 @@ fn write_rust_function_decl_impl(
947
991
if needs_comma {
948
992
write ! ( out, ", " ) ;
949
993
}
950
- match sig. ret . as_ref ( ) . unwrap ( ) {
951
- Type :: Ref ( ret) => {
952
- write_type_space ( out, & ret. inner ) ;
953
- if !ret. mutable {
954
- write ! ( out, "const " ) ;
994
+ if sig. constructor {
995
+ write ! (
996
+ out,
997
+ "{} " ,
998
+ out. types. resolve( self_type. as_ref( ) . unwrap( ) ) . name. cxx
999
+ ) ;
1000
+ } else {
1001
+ match sig. ret . as_ref ( ) . unwrap ( ) {
1002
+ Type :: Ref ( ret) => {
1003
+ write_type_space ( out, & ret. inner ) ;
1004
+ if !ret. mutable {
1005
+ write ! ( out, "const " ) ;
1006
+ }
1007
+ write ! ( out, "*" ) ;
955
1008
}
956
- write ! ( out, "*" ) ;
1009
+ ret => write_type_space ( out, ret ) ,
957
1010
}
958
- ret => write_type_space ( out, ret) ,
959
1011
}
960
1012
write ! ( out, "*return$" ) ;
961
1013
needs_comma = true ;
@@ -982,7 +1034,15 @@ fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
982
1034
let doc = & efn. doc ;
983
1035
let invoke = mangle:: extern_fn ( efn, out. types ) ;
984
1036
let indirect_call = false ;
985
- write_rust_function_shim_impl ( out, & local_name, efn, & efn. self_type , doc, & invoke, indirect_call) ;
1037
+ write_rust_function_shim_impl (
1038
+ out,
1039
+ & local_name,
1040
+ efn,
1041
+ & efn. self_type ,
1042
+ doc,
1043
+ & invoke,
1044
+ indirect_call,
1045
+ ) ;
986
1046
}
987
1047
988
1048
fn write_rust_function_shim_decl (
@@ -993,12 +1053,18 @@ fn write_rust_function_shim_decl(
993
1053
indirect_call : bool ,
994
1054
) {
995
1055
begin_function_definition ( out) ;
996
- write_return_type ( out, & sig. ret ) ;
1056
+ if !sig. constructor {
1057
+ write_return_type ( out, & sig. ret ) ;
1058
+ }
997
1059
if let Some ( self_type) = self_type {
998
- write ! ( out, "{}::{}(" , out. types. resolve( self_type) . name. cxx, local_name) ;
1060
+ let cxx_name = & out. types . resolve ( self_type) . name . cxx ;
1061
+ if sig. constructor {
1062
+ write ! ( out, "{}::{}(" , cxx_name, cxx_name) ;
1063
+ } else {
1064
+ write ! ( out, "{}::{}(" , cxx_name, local_name) ;
1065
+ }
999
1066
} else {
1000
1067
write ! ( out, "{}(" , local_name) ;
1001
-
1002
1068
}
1003
1069
for ( i, arg) in sig. args . iter ( ) . enumerate ( ) {
1004
1070
if i > 0 {
@@ -1059,20 +1125,22 @@ fn write_rust_function_shim_impl(
1059
1125
write ! ( out, " " ) ;
1060
1126
let indirect_return = indirect_return ( sig, out. types ) ;
1061
1127
if indirect_return {
1062
- out. builtin . maybe_uninit = true ;
1063
- write ! ( out, "::rust::MaybeUninit<" ) ;
1064
- match sig. ret . as_ref ( ) . unwrap ( ) {
1065
- Type :: Ref ( ret) => {
1066
- write_type_space ( out, & ret. inner ) ;
1067
- if !ret. mutable {
1068
- write ! ( out, "const " ) ;
1128
+ if !sig. constructor {
1129
+ out. builtin . maybe_uninit = true ;
1130
+ write ! ( out, "::rust::MaybeUninit<" ) ;
1131
+ match sig. ret . as_ref ( ) . unwrap ( ) {
1132
+ Type :: Ref ( ret) => {
1133
+ write_type_space ( out, & ret. inner ) ;
1134
+ if !ret. mutable {
1135
+ write ! ( out, "const " ) ;
1136
+ }
1137
+ write ! ( out, "*" ) ;
1069
1138
}
1070
- write ! ( out, "*" ) ;
1139
+ ret => write_type ( out, ret ) ,
1071
1140
}
1072
- ret => write_type ( out, ret) ,
1141
+ writeln ! ( out, "> return$;" ) ;
1142
+ write ! ( out, " " ) ;
1073
1143
}
1074
- writeln ! ( out, "> return$;" ) ;
1075
- write ! ( out, " " ) ;
1076
1144
} else if let Some ( ret) = & sig. ret {
1077
1145
write ! ( out, "return " ) ;
1078
1146
match ret {
@@ -1128,7 +1196,11 @@ fn write_rust_function_shim_impl(
1128
1196
if needs_comma {
1129
1197
write ! ( out, ", " ) ;
1130
1198
}
1131
- write ! ( out, "&return$.value" ) ;
1199
+ if sig. constructor {
1200
+ write ! ( out, "this" ) ;
1201
+ } else {
1202
+ write ! ( out, "&return$.value" ) ;
1203
+ }
1132
1204
needs_comma = true ;
1133
1205
}
1134
1206
if indirect_call {
@@ -1152,7 +1224,7 @@ fn write_rust_function_shim_impl(
1152
1224
writeln ! ( out, " throw ::rust::impl<::rust::Error>::error(error$);" ) ;
1153
1225
writeln ! ( out, " }}" ) ;
1154
1226
}
1155
- if indirect_return {
1227
+ if indirect_return && !sig . constructor {
1156
1228
write ! ( out, " return " ) ;
1157
1229
match sig. ret . as_ref ( ) . unwrap ( ) {
1158
1230
Type :: Ref ( _) => write ! ( out, "*return$.value" ) ,
@@ -1174,9 +1246,11 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
1174
1246
}
1175
1247
1176
1248
fn indirect_return ( sig : & Signature , types : & Types ) -> bool {
1177
- sig. ret
1178
- . as_ref ( )
1179
- . is_some_and ( |ret| sig. throws || types. needs_indirect_abi ( ret) )
1249
+ sig. constructor
1250
+ || sig
1251
+ . ret
1252
+ . as_ref ( )
1253
+ . is_some_and ( |ret| sig. throws || types. needs_indirect_abi ( ret) )
1180
1254
}
1181
1255
1182
1256
fn write_indirect_return_type ( out : & mut OutFile , ty : & Type ) {
0 commit comments