@@ -262,6 +262,10 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
262262 write_doc ( out, "" , & strct. doc ) ;
263263 writeln ! ( out, "struct {} final {{" , strct. name. cxx) ;
264264
265+ if methods. iter ( ) . any ( |method| method. sig . constructor ) {
266+ writeln ! ( out, "{}() = default;" , strct. name. cxx) ;
267+ }
268+
265269 for field in & strct. fields {
266270 write_doc ( out, " " , & field. doc ) ;
267271 write ! ( out, " " ) ;
@@ -278,9 +282,12 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
278282 write_doc ( out, " " , & method. doc ) ;
279283 write ! ( out, " " ) ;
280284 let sig = & method. sig ;
281- let local_name = method. name . cxx . to_string ( ) ;
285+ let local_name = match ( & method. self_type , sig. constructor ) {
286+ ( Some ( self_type) , true ) => out. types . resolve ( self_type) . name . cxx . to_string ( ) ,
287+ _ => method. name . cxx . to_string ( ) ,
288+ } ;
282289 let indirect_call = false ;
283- if method. self_type . is_some ( ) {
290+ if method. self_type . is_some ( ) && !method . sig . constructor {
284291 write ! ( out, "static " ) ;
285292 }
286293 write_rust_function_shim_decl ( out, & local_name, sig, & None , indirect_call) ;
@@ -375,7 +382,7 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
375382 let sig = & method. sig ;
376383 let local_name = method. name . cxx . to_string ( ) ;
377384 let indirect_call = false ;
378- if method. self_type . is_some ( ) {
385+ if method. self_type . is_some ( ) && !method . sig . constructor {
379386 write ! ( out, "static " ) ;
380387 }
381388 write_rust_function_shim_decl ( out, & local_name, sig, & None , indirect_call) ;
@@ -754,51 +761,61 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
754761 if !efn. args . is_empty ( ) || efn. receiver . is_some ( ) {
755762 write ! ( out, ", " ) ;
756763 }
757- write_indirect_return_type_space ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
764+ if efn. sig . constructor {
765+ write ! (
766+ out,
767+ "{} " ,
768+ out. types. resolve( efn. self_type. as_ref( ) . unwrap( ) ) . name. cxx
769+ ) ;
770+ } else {
771+ write_indirect_return_type_space ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
772+ }
758773 write ! ( out, "*return$" ) ;
759774 }
760775 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, ", " ) ;
776+ if !efn. sig . constructor {
777+ write ! ( out, " " ) ;
778+ write_return_type ( out, & efn. ret ) ;
779+ match & efn. receiver {
780+ None => write ! ( out, "(*{}$)(" , efn. name. rust) ,
781+ Some ( receiver) => write ! (
782+ out,
783+ "({}::*{}$)(" ,
784+ out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
785+ efn. name. rust,
786+ ) ,
775787 }
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" ) ;
788+ for ( i, arg) in efn. args . iter ( ) . enumerate ( ) {
789+ if i > 0 {
790+ write ! ( out, ", " ) ;
791+ }
792+ write_type ( out, & arg. ty ) ;
782793 }
794+ write ! ( out, ")" ) ;
795+ if let Some ( receiver) = & efn. receiver {
796+ if !receiver. mutable {
797+ write ! ( out, " const" ) ;
798+ }
799+ }
800+ write ! ( out, " = " ) ;
801+ match ( & efn. receiver , & efn. self_type ) {
802+ ( None , None ) => write ! ( out, "{}" , efn. name. to_fully_qualified( ) ) ,
803+ ( Some ( receiver) , None ) => write ! (
804+ out,
805+ "&{}::{}" ,
806+ out. types. resolve( & receiver. ty) . name. to_fully_qualified( ) ,
807+ efn. name. cxx,
808+ ) ,
809+ ( None , Some ( self_type) ) => write ! (
810+ out,
811+ "&{}::{}" ,
812+ out. types. resolve( self_type) . name. to_fully_qualified( ) ,
813+ efn. name. cxx,
814+ ) ,
815+ _ => unreachable ! ( "receiver and self_type are mutually exclusive" ) ,
816+ }
817+ writeln ! ( out, ";" ) ;
783818 }
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, ";" ) ;
802819 write ! ( out, " " ) ;
803820 if efn. throws {
804821 out. builtin . ptr_len = true ;
@@ -811,28 +828,38 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
811828 if indirect_return {
812829 out. include . new = true ;
813830 write ! ( out, "new (return$) " ) ;
814- write_indirect_return_type ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
831+ if efn. sig . constructor {
832+ write ! (
833+ out,
834+ "{}" ,
835+ out. types. resolve( efn. self_type. as_ref( ) . unwrap( ) ) . name. cxx
836+ ) ;
837+ } else {
838+ write_indirect_return_type ( out, efn. ret . as_ref ( ) . unwrap ( ) ) ;
839+ }
815840 write ! ( out, "(" ) ;
816841 } else if efn. ret . is_some ( ) {
817842 write ! ( out, "return " ) ;
818843 }
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(" ) ;
844+ if !efn. sig . constructor {
845+ match & efn. ret {
846+ Some ( Type :: Ref ( _) ) => write ! ( out, "&" ) ,
847+ Some ( Type :: Str ( _) ) if !indirect_return => {
848+ out. builtin . rust_str_repr = true ;
849+ write ! ( out, "::rust::impl<::rust::Str>::repr(" ) ;
850+ }
851+ Some ( ty @ Type :: SliceRef ( _) ) if !indirect_return => {
852+ out. builtin . rust_slice_repr = true ;
853+ write ! ( out, "::rust::impl<" ) ;
854+ write_type ( out, ty) ;
855+ write ! ( out, ">::repr(" ) ;
856+ }
857+ _ => { }
824858 }
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(" ) ;
859+ match & efn. receiver {
860+ None => write ! ( out, "{}$(" , efn. name. rust) ,
861+ Some ( _) => write ! ( out, "(self.*{}$)(" , efn. name. rust) ,
830862 }
831- _ => { }
832- }
833- match & efn. receiver {
834- None => write ! ( out, "{}$(" , efn. name. rust) ,
835- Some ( _) => write ! ( out, "(self.*{}$)(" , efn. name. rust) ,
836863 }
837864 for ( i, arg) in efn. args . iter ( ) . enumerate ( ) {
838865 if i > 0 {
@@ -862,7 +889,9 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
862889 write ! ( out, "{}" , arg. name. cxx) ;
863890 }
864891 }
865- write ! ( out, ")" ) ;
892+ if !efn. sig . constructor {
893+ write ! ( out, ")" ) ;
894+ }
866895 match & efn. ret {
867896 Some ( Type :: RustBox ( _) ) => write ! ( out, ".into_raw()" ) ,
868897 Some ( Type :: UniquePtr ( _) ) => write ! ( out, ".release()" ) ,
@@ -892,27 +921,36 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
892921fn write_function_pointer_trampoline ( out : & mut OutFile , efn : & ExternFn , var : & Pair , f : & Signature ) {
893922 let r_trampoline = mangle:: r_trampoline ( efn, var, out. types ) ;
894923 let indirect_call = true ;
895- write_rust_function_decl_impl ( out, & r_trampoline, f, indirect_call) ;
924+ write_rust_function_decl_impl ( out, & r_trampoline, f, & efn . self_type , indirect_call) ;
896925
897926 out. next_section ( ) ;
898927 let c_trampoline = mangle:: c_trampoline ( efn, var, out. types ) . to_string ( ) ;
899928 let doc = Doc :: new ( ) ;
900- write_rust_function_shim_impl ( out, & c_trampoline, f, & efn. self_type , & doc, & r_trampoline, indirect_call) ;
929+ write_rust_function_shim_impl (
930+ out,
931+ & c_trampoline,
932+ f,
933+ & efn. self_type ,
934+ & doc,
935+ & r_trampoline,
936+ indirect_call,
937+ ) ;
901938}
902939
903940fn write_rust_function_decl < ' a > ( out : & mut OutFile < ' a > , efn : & ' a ExternFn ) {
904941 out. set_namespace ( & efn. name . namespace ) ;
905942 out. begin_block ( Block :: ExternC ) ;
906943 let link_name = mangle:: extern_fn ( efn, out. types ) ;
907944 let indirect_call = false ;
908- write_rust_function_decl_impl ( out, & link_name, efn, indirect_call) ;
945+ write_rust_function_decl_impl ( out, & link_name, efn, & efn . self_type , indirect_call) ;
909946 out. end_block ( Block :: ExternC ) ;
910947}
911948
912949fn write_rust_function_decl_impl (
913950 out : & mut OutFile ,
914951 link_name : & Symbol ,
915952 sig : & Signature ,
953+ self_type : & Option < Ident > ,
916954 indirect_call : bool ,
917955) {
918956 out. next_section ( ) ;
@@ -947,15 +985,23 @@ fn write_rust_function_decl_impl(
947985 if needs_comma {
948986 write ! ( out, ", " ) ;
949987 }
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 " ) ;
988+ if sig. constructor {
989+ write ! (
990+ out,
991+ "{} " ,
992+ out. types. resolve( self_type. as_ref( ) . unwrap( ) ) . name. cxx
993+ ) ;
994+ } else {
995+ match sig. ret . as_ref ( ) . unwrap ( ) {
996+ Type :: Ref ( ret) => {
997+ write_type_space ( out, & ret. inner ) ;
998+ if !ret. mutable {
999+ write ! ( out, "const " ) ;
1000+ }
1001+ write ! ( out, "*" ) ;
9551002 }
956- write ! ( out, "*" ) ;
1003+ ret => write_type_space ( out, ret ) ,
9571004 }
958- ret => write_type_space ( out, ret) ,
9591005 }
9601006 write ! ( out, "*return$" ) ;
9611007 needs_comma = true ;
@@ -982,7 +1028,15 @@ fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
9821028 let doc = & efn. doc ;
9831029 let invoke = mangle:: extern_fn ( efn, out. types ) ;
9841030 let indirect_call = false ;
985- write_rust_function_shim_impl ( out, & local_name, efn, & efn. self_type , doc, & invoke, indirect_call) ;
1031+ write_rust_function_shim_impl (
1032+ out,
1033+ & local_name,
1034+ efn,
1035+ & efn. self_type ,
1036+ doc,
1037+ & invoke,
1038+ indirect_call,
1039+ ) ;
9861040}
9871041
9881042fn write_rust_function_shim_decl (
@@ -993,12 +1047,18 @@ fn write_rust_function_shim_decl(
9931047 indirect_call : bool ,
9941048) {
9951049 begin_function_definition ( out) ;
996- write_return_type ( out, & sig. ret ) ;
1050+ if !sig. constructor {
1051+ write_return_type ( out, & sig. ret ) ;
1052+ }
9971053 if let Some ( self_type) = self_type {
998- write ! ( out, "{}::{}(" , out. types. resolve( self_type) . name. cxx, local_name) ;
1054+ let cxx_name = & out. types . resolve ( self_type) . name . cxx ;
1055+ if sig. constructor {
1056+ write ! ( out, "{}::{}(" , cxx_name, cxx_name) ;
1057+ } else {
1058+ write ! ( out, "{}::{}(" , cxx_name, local_name) ;
1059+ }
9991060 } else {
10001061 write ! ( out, "{}(" , local_name) ;
1001-
10021062 }
10031063 for ( i, arg) in sig. args . iter ( ) . enumerate ( ) {
10041064 if i > 0 {
@@ -1059,20 +1119,22 @@ fn write_rust_function_shim_impl(
10591119 write ! ( out, " " ) ;
10601120 let indirect_return = indirect_return ( sig, out. types ) ;
10611121 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 " ) ;
1122+ if !sig. constructor {
1123+ out. builtin . maybe_uninit = true ;
1124+ write ! ( out, "::rust::MaybeUninit<" ) ;
1125+ match sig. ret . as_ref ( ) . unwrap ( ) {
1126+ Type :: Ref ( ret) => {
1127+ write_type_space ( out, & ret. inner ) ;
1128+ if !ret. mutable {
1129+ write ! ( out, "const " ) ;
1130+ }
1131+ write ! ( out, "*" ) ;
10691132 }
1070- write ! ( out, "*" ) ;
1133+ ret => write_type ( out, ret ) ,
10711134 }
1072- ret => write_type ( out, ret) ,
1135+ writeln ! ( out, "> return$;" ) ;
1136+ write ! ( out, " " ) ;
10731137 }
1074- writeln ! ( out, "> return$;" ) ;
1075- write ! ( out, " " ) ;
10761138 } else if let Some ( ret) = & sig. ret {
10771139 write ! ( out, "return " ) ;
10781140 match ret {
@@ -1128,7 +1190,11 @@ fn write_rust_function_shim_impl(
11281190 if needs_comma {
11291191 write ! ( out, ", " ) ;
11301192 }
1131- write ! ( out, "&return$.value" ) ;
1193+ if sig. constructor {
1194+ write ! ( out, "this" ) ;
1195+ } else {
1196+ write ! ( out, "&return$.value" ) ;
1197+ }
11321198 needs_comma = true ;
11331199 }
11341200 if indirect_call {
@@ -1152,7 +1218,7 @@ fn write_rust_function_shim_impl(
11521218 writeln ! ( out, " throw ::rust::impl<::rust::Error>::error(error$);" ) ;
11531219 writeln ! ( out, " }}" ) ;
11541220 }
1155- if indirect_return {
1221+ if indirect_return && !sig . constructor {
11561222 write ! ( out, " return " ) ;
11571223 match sig. ret . as_ref ( ) . unwrap ( ) {
11581224 Type :: Ref ( _) => write ! ( out, "*return$.value" ) ,
@@ -1174,9 +1240,11 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
11741240}
11751241
11761242fn 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) )
1243+ sig. constructor
1244+ || sig
1245+ . ret
1246+ . as_ref ( )
1247+ . is_some_and ( |ret| sig. throws || types. needs_indirect_abi ( ret) )
11801248}
11811249
11821250fn write_indirect_return_type ( out : & mut OutFile , ty : & Type ) {
0 commit comments