@@ -62,7 +62,7 @@ struct CSig {
6262enum Scalar {
6363 Void ,
6464 OptionBool ( Type ) ,
65- ResultEnum { err : TypeId , max_err : usize } ,
65+ Result ( bool ) ,
6666 Type ( Type ) ,
6767}
6868
@@ -399,24 +399,19 @@ impl Return {
399399 return ;
400400 }
401401
402- // Unpack `result<T, E>` returns where `E` looks like an enum
403- // so we can return that in the scalar return and have `T` get
404- // returned through the normal returns.
402+ // Unpack a result as a boolean return type, with two
403+ // return pointers for ok and err values
405404 TypeDefKind :: Result ( r) => {
406- if let Some ( Type :: Id ( err) ) = r. err {
407- if let TypeDefKind :: Enum ( enum_) = & iface. types [ err] . kind {
408- self . scalar = Some ( Scalar :: ResultEnum {
409- err,
410- max_err : enum_. cases . len ( ) ,
411- } ) ;
412- if let Some ( ok) = r. ok {
413- self . retptrs . push ( ok) ;
414- }
415- return ;
416- }
405+ let mut has_ok_type = false ;
406+ if let Some ( ok) = r. ok {
407+ has_ok_type = true ;
408+ self . retptrs . push ( ok) ;
417409 }
418-
419- // fall through to the return pointer case
410+ if let Some ( err) = r. err {
411+ self . retptrs . push ( err) ;
412+ }
413+ self . scalar = Some ( Scalar :: Result ( has_ok_type) ) ;
414+ return ;
420415 }
421416
422417 // These types are always returned indirectly.
@@ -612,13 +607,6 @@ impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
612607 i,
613608 ) ;
614609 }
615- uwriteln ! (
616- self . src. h_defs,
617- "#define {}_RESULT_{}_OK {}" ,
618- self . name. to_shouty_snake_case( ) ,
619- name. to_shouty_snake_case( ) ,
620- int_max_str( enum_. tag( ) )
621- ) ;
622610
623611 self . types
624612 . insert ( id, mem:: replace ( & mut self . src . h_defs , prev) ) ;
@@ -869,13 +857,17 @@ impl InterfaceGenerator<'_> {
869857 self . gen . names . insert ( & name) . expect ( "duplicate symbols" ) ;
870858
871859 let start = self . src . h_fns . len ( ) ;
860+ let mut result_rets = false ;
861+ let mut result_rets_has_ok_type = false ;
872862
873863 let ret = self . classify_ret ( func) ;
874864 match & ret. scalar {
875865 None | Some ( Scalar :: Void ) => self . src . h_fns ( "void" ) ,
876866 Some ( Scalar :: OptionBool ( _id) ) => self . src . h_fns ( "bool" ) ,
877- Some ( Scalar :: ResultEnum { err, .. } ) => {
878- self . print_ty ( SourceType :: HFns , & Type :: Id ( * err) )
867+ Some ( Scalar :: Result ( has_ok_type) ) => {
868+ result_rets = true ;
869+ result_rets_has_ok_type = * has_ok_type;
870+ self . src . h_fns ( "bool" ) ;
879871 }
880872 Some ( Scalar :: Type ( ty) ) => self . print_ty ( SourceType :: HFns , ty) ,
881873 }
@@ -905,7 +897,14 @@ impl InterfaceGenerator<'_> {
905897 }
906898 self . print_ty ( SourceType :: HFns , ty) ;
907899 self . src . h_fns ( " *" ) ;
908- let name: String = if single_ret {
900+ let name: String = if result_rets {
901+ assert ! ( i <= 1 ) ;
902+ if i == 0 && result_rets_has_ok_type {
903+ "ret" . into ( )
904+ } else {
905+ "err" . into ( )
906+ }
907+ } else if single_ret {
909908 "ret" . into ( )
910909 } else {
911910 format ! ( "ret{}" , i)
@@ -1420,6 +1419,7 @@ struct FunctionBindgen<'a, 'b> {
14201419 payloads : Vec < String > ,
14211420 params : Vec < String > ,
14221421 wasm_return : Option < String > ,
1422+ ret_store_cnt : usize ,
14231423}
14241424
14251425impl < ' a , ' b > FunctionBindgen < ' a , ' b > {
@@ -1439,6 +1439,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
14391439 payloads : Vec :: new ( ) ,
14401440 params : Vec :: new ( ) ,
14411441 wasm_return : None ,
1442+ ret_store_cnt : 0 ,
14421443 }
14431444 }
14441445
@@ -1470,11 +1471,16 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
14701471 ) ;
14711472 }
14721473
1473- fn store_in_retptrs ( & mut self , operands : & [ String ] ) {
1474- assert_eq ! ( operands. len( ) , self . sig. retptrs. len( ) ) ;
1475- for ( op, ptr) in operands. iter ( ) . zip ( self . sig . retptrs . clone ( ) ) {
1476- self . store_op ( op, & format ! ( "*{}" , ptr) ) ;
1477- }
1474+ fn store_in_retptr ( & mut self , operand : & String ) {
1475+ self . store_op (
1476+ operand,
1477+ & format ! ( "*{}" , self . sig. retptrs[ self . ret_store_cnt] ) ,
1478+ ) ;
1479+ self . ret_store_cnt = self . ret_store_cnt + 1 ;
1480+ }
1481+
1482+ fn check_all_retptrs_written ( & self ) {
1483+ assert ! ( self . ret_store_cnt == self . sig. retptrs. len( ) ) ;
14781484 }
14791485}
14801486
@@ -2162,88 +2168,120 @@ impl Bindgen for FunctionBindgen<'_, '_> {
21622168 ) ;
21632169 results. push ( option_ret) ;
21642170 }
2165- Some ( Scalar :: ResultEnum { err, max_err } ) => {
2171+ Some ( Scalar :: Result ( has_ok_type) ) => {
2172+ let result_ty = self
2173+ . gen
2174+ . type_string ( func. results . iter_types ( ) . next ( ) . unwrap ( ) ) ;
21662175 let ret = self . locals . tmp ( "ret" ) ;
2167- let mut ok_names = Vec :: new ( ) ;
2168- for ty in self . sig . ret . retptrs . iter ( ) {
2169- let val = self . locals . tmp ( "ok" ) ;
2176+ let mut ret_iter = self . sig . ret . retptrs . iter ( ) ;
2177+ uwriteln ! ( self . src, "{result_ty} {ret};" ) ;
2178+ let ok_name = if * has_ok_type {
2179+ if let Some ( ty) = ret_iter. next ( ) {
2180+ let val = self . locals . tmp ( "ok" ) ;
2181+ if args. len ( ) > 0 {
2182+ uwrite ! ( args, ", " ) ;
2183+ }
2184+ uwrite ! ( args, "&{val}" ) ;
2185+ let ty = self . gen . type_string ( ty) ;
2186+ uwriteln ! ( self . src, "{} {};" , ty, val) ;
2187+ Some ( val)
2188+ } else {
2189+ None
2190+ }
2191+ } else {
2192+ None
2193+ } ;
2194+ let err_name = if let Some ( ty) = ret_iter. next ( ) {
2195+ let val = self . locals . tmp ( "err" ) ;
21702196 if args. len ( ) > 0 {
2171- args . push_str ( ", " ) ;
2197+ uwrite ! ( args , ", " )
21722198 }
2173- args. push_str ( "&" ) ;
2174- args. push_str ( & val) ;
2199+ uwrite ! ( args, "&{val}" ) ;
21752200 let ty = self . gen . type_string ( ty) ;
21762201 uwriteln ! ( self . src, "{} {};" , ty, val) ;
2177- ok_names. push ( val) ;
2202+ Some ( val)
2203+ } else {
2204+ None
2205+ } ;
2206+ assert ! ( ret_iter. next( ) . is_none( ) ) ;
2207+ uwrite ! ( self . src, "" ) ;
2208+ uwriteln ! ( self . src, "{ret}.is_err = {}({args});" , self . sig. name) ;
2209+
2210+ if let Some ( err_name) = err_name {
2211+ uwriteln ! (
2212+ self . src,
2213+ "if ({ret}.is_err) {{
2214+ {ret}.val.err = {err_name};
2215+ }}" ,
2216+ ) ;
2217+ }
2218+ if let Some ( ok_name) = ok_name {
2219+ uwriteln ! (
2220+ self . src,
2221+ "if (!{ret}.is_err) {{
2222+ {ret}.val.ok = {ok_name};
2223+ }}"
2224+ ) ;
2225+ } else {
2226+ uwrite ! ( self . src, "\n " ) ;
2227+ }
2228+ results. push ( ret) ;
2229+ }
2230+ }
2231+ }
2232+ Instruction :: Return { .. } if self . gen . in_import => {
2233+ match self . sig . ret . scalar {
2234+ None => {
2235+ for op in operands. iter ( ) {
2236+ self . store_in_retptr ( op) ;
2237+ }
2238+ }
2239+ Some ( Scalar :: Void ) => {
2240+ assert ! ( operands. is_empty( ) ) ;
2241+ }
2242+ Some ( Scalar :: Type ( _) ) => {
2243+ assert_eq ! ( operands. len( ) , 1 ) ;
2244+ self . src . push_str ( "return " ) ;
2245+ self . src . push_str ( & operands[ 0 ] ) ;
2246+ self . src . push_str ( ";\n " ) ;
2247+ }
2248+ Some ( Scalar :: OptionBool ( _) ) => {
2249+ assert_eq ! ( operands. len( ) , 1 ) ;
2250+ let variant = & operands[ 0 ] ;
2251+ self . store_in_retptr ( & format ! ( "{}.val" , variant) ) ;
2252+ self . src . push_str ( "return " ) ;
2253+ self . src . push_str ( & variant) ;
2254+ self . src . push_str ( ".is_some;\n " ) ;
2255+ }
2256+ Some ( Scalar :: Result ( has_ok_type) ) => {
2257+ assert_eq ! ( operands. len( ) , 1 ) ;
2258+ let variant = & operands[ 0 ] ;
2259+ assert ! ( self . sig. retptrs. len( ) <= 2 ) ;
2260+ uwriteln ! ( self . src, "if (!{}.is_err) {{" , variant) ;
2261+ if self . sig . retptrs . len ( ) == 2 {
2262+ self . store_in_retptr ( & format ! ( "{}.val.ok" , variant) ) ;
2263+ } else if self . sig . retptrs . len ( ) == 1 && has_ok_type {
2264+ self . store_in_retptr ( & format ! ( "{}.val.ok" , variant) ) ;
21782265 }
2179- let err_ty = self . gen . type_string ( & Type :: Id ( * err) ) ;
21802266 uwriteln ! (
21812267 self . src,
2182- "{} {} = {}({});" ,
2183- err_ty,
2184- ret,
2185- self . sig. name,
2186- args,
2268+ " return 0;
2269+ }} else {{"
21872270 ) ;
2188- let result_ty = self
2189- . gen
2190- . type_string ( func. results . iter_types ( ) . next ( ) . unwrap ( ) ) ;
2191- let result_ret = self . locals . tmp ( "ret" ) ;
2192- uwrite ! (
2271+ if self . sig . retptrs . len ( ) == 2 {
2272+ self . store_in_retptr ( & format ! ( "{}.val.err" , variant) ) ;
2273+ } else if self . sig . retptrs . len ( ) == 1 && !has_ok_type {
2274+ self . store_in_retptr ( & format ! ( "{}.val.err" , variant) ) ;
2275+ }
2276+ uwriteln ! (
21932277 self . src,
2194- "
2195- {ty} {ret};
2196- if ({tag} <= {max}) {{
2197- {ret}.is_err = true;
2198- {ret}.val.err = {tag};
2199- }} else {{
2200- {ret}.is_err = false;
2201- {set_ok}
2202- }}
2203- " ,
2204- ty = result_ty,
2205- ret = result_ret,
2206- tag = ret,
2207- max = max_err,
2208- set_ok = if self . sig. ret. retptrs. len( ) == 0 {
2209- String :: new( )
2210- } else {
2211- let name = ok_names. pop( ) . unwrap( ) ;
2212- format!( "{}.val.ok = {};" , result_ret, name)
2213- } ,
2278+ " return 1;
2279+ }}"
22142280 ) ;
2215- results. push ( result_ret) ;
22162281 }
22172282 }
2283+ self . check_all_retptrs_written ( ) ;
22182284 }
2219- Instruction :: Return { .. } if self . gen . in_import => match self . sig . ret . scalar {
2220- None => self . store_in_retptrs ( operands) ,
2221- Some ( Scalar :: Void ) => {
2222- assert ! ( operands. is_empty( ) ) ;
2223- }
2224- Some ( Scalar :: Type ( _) ) => {
2225- assert_eq ! ( operands. len( ) , 1 ) ;
2226- self . src . push_str ( "return " ) ;
2227- self . src . push_str ( & operands[ 0 ] ) ;
2228- self . src . push_str ( ";\n " ) ;
2229- }
2230- Some ( Scalar :: OptionBool ( _) ) => {
2231- assert_eq ! ( operands. len( ) , 1 ) ;
2232- let variant = & operands[ 0 ] ;
2233- self . store_in_retptrs ( & [ format ! ( "{}.val" , variant) ] ) ;
2234- self . src . push_str ( "return " ) ;
2235- self . src . push_str ( & variant) ;
2236- self . src . push_str ( ".is_some;\n " ) ;
2237- }
2238- Some ( Scalar :: ResultEnum { .. } ) => {
2239- assert_eq ! ( operands. len( ) , 1 ) ;
2240- let variant = & operands[ 0 ] ;
2241- if self . sig . retptrs . len ( ) > 0 {
2242- self . store_in_retptrs ( & [ format ! ( "{}.val.ok" , variant) ] ) ;
2243- }
2244- uwriteln ! ( self . src, "return {}.is_err ? {0}.val.err : -1;" , variant) ;
2245- }
2246- } ,
22472285 Instruction :: Return { amt, .. } => {
22482286 assert ! ( * amt <= 1 ) ;
22492287 if * amt == 1 {
@@ -2407,15 +2445,6 @@ fn int_repr(ty: Int) -> &'static str {
24072445 }
24082446}
24092447
2410- fn int_max_str ( ty : Int ) -> String {
2411- match ty {
2412- Int :: U8 => u8:: MAX . to_string ( ) ,
2413- Int :: U16 => u16:: MAX . to_string ( ) ,
2414- Int :: U32 => u32:: MAX . to_string ( ) ,
2415- Int :: U64 => u64:: MAX . to_string ( ) ,
2416- }
2417- }
2418-
24192448fn flags_repr ( f : & Flags ) -> Int {
24202449 match f. repr ( ) {
24212450 FlagsRepr :: U8 => Int :: U8 ,
0 commit comments