@@ -24,8 +24,14 @@ impl BuiltInResult {
24
24
// TODO: Choose the kind of Result representation based on whether or not the ok and error
25
25
// types are primitives.
26
26
// See `swift-bridge/src/std_bridge/result`
27
- let result_kind = quote ! {
28
- ResultPtrAndPtr
27
+ let result_kind = if self . ok_ty . can_be_encoded_with_zero_bytes ( ) {
28
+ quote ! {
29
+ ResultVoidAndPtr
30
+ }
31
+ } else {
32
+ quote ! {
33
+ ResultPtrAndPtr
34
+ }
29
35
} ;
30
36
31
37
quote ! {
@@ -54,18 +60,37 @@ impl BuiltInResult {
54
60
span,
55
61
) ;
56
62
57
- quote ! {
58
- match #expression {
59
- Ok ( ok) => {
60
- #swift_bridge_path:: result:: ResultPtrAndPtr {
61
- is_ok: true ,
62
- ok_or_err: #convert_ok as * mut std:: ffi:: c_void
63
+ if self . ok_ty . can_be_encoded_with_zero_bytes ( ) {
64
+ quote ! {
65
+ match #expression {
66
+ Ok ( ok) => {
67
+ #swift_bridge_path:: result:: ResultVoidAndPtr {
68
+ is_ok: true ,
69
+ err: std:: ptr:: null_mut:: <std:: ffi:: c_void>( )
70
+ }
71
+ }
72
+ Err ( err) => {
73
+ #swift_bridge_path:: result:: ResultVoidAndPtr {
74
+ is_ok: false ,
75
+ err: #convert_err as * mut std:: ffi:: c_void
76
+ }
63
77
}
64
78
}
65
- Err ( err) => {
66
- #swift_bridge_path:: result:: ResultPtrAndPtr {
67
- is_ok: false ,
68
- ok_or_err: #convert_err as * mut std:: ffi:: c_void
79
+ }
80
+ } else {
81
+ quote ! {
82
+ match #expression {
83
+ Ok ( ok) => {
84
+ #swift_bridge_path:: result:: ResultPtrAndPtr {
85
+ is_ok: true ,
86
+ ok_or_err: #convert_ok as * mut std:: ffi:: c_void
87
+ }
88
+ }
89
+ Err ( err) => {
90
+ #swift_bridge_path:: result:: ResultPtrAndPtr {
91
+ is_ok: false ,
92
+ ok_or_err: #convert_err as * mut std:: ffi:: c_void
93
+ }
69
94
}
70
95
}
71
96
}
@@ -129,18 +154,44 @@ impl BuiltInResult {
129
154
type_pos : TypePosition ,
130
155
types : & TypeDeclarations ,
131
156
) -> String {
132
- let convert_ok =
133
- self . ok_ty
134
- . convert_ffi_expression_to_swift_type ( "val.ok_or_err!" , type_pos, types) ;
135
- let convert_err =
136
- self . err_ty
137
- . convert_ffi_expression_to_swift_type ( "val.ok_or_err!" , type_pos, types) ;
157
+ let ( mut ok, err) = if let Some ( zero_byte_encoding) = self . ok_ty . only_encoding ( ) {
158
+ let ok = zero_byte_encoding. swift ;
159
+ let convert_err = self
160
+ . err_ty
161
+ . convert_ffi_expression_to_swift_type ( "val.err!" , type_pos, types) ;
162
+
163
+ ( ok, convert_err)
164
+ } else {
165
+ let convert_ok =
166
+ self . ok_ty
167
+ . convert_ffi_expression_to_swift_type ( "val.ok_or_err!" , type_pos, types) ;
168
+ let convert_err =
169
+ self . err_ty
170
+ . convert_ffi_expression_to_swift_type ( "val.ok_or_err!" , type_pos, types) ;
171
+
172
+ ( convert_ok, convert_err)
173
+ } ;
174
+
175
+ // There is a Swift compiler bug in Xcode 13 where using an explicit `()` here somehow leads
176
+ // the Swift compiler to a compile time error:
177
+ // "Unable to infer complex closure return type; add explicit type to disambiguate"
178
+ //
179
+ // It's asking us to add a `{ () -> () in .. }` explicit type to the beginning of our closure.
180
+ //
181
+ // To solve this bug we can either add that explicit closure type, or remove the explicit
182
+ // `return ()` in favor of a `return`.. Not sure why making the return type less explicit
183
+ // solves the compile time error.. But it does..
184
+ //
185
+ // As mentioned, this doesn't seem to happen in Xcode 14.
186
+ // So, we can remove this if statement whenever we stop supporting Xcode 13.
187
+ if self . ok_ty . is_null ( ) {
188
+ ok = "" . to_string ( ) ;
189
+ }
138
190
139
191
format ! (
140
192
"try {{ let val = {expression}; if val.is_ok {{ return {ok} }} else {{ throw {err} }} }}()" ,
141
193
expression = expression,
142
- ok = convert_ok,
143
- err = convert_err
194
+ err = err
144
195
)
145
196
}
146
197
@@ -156,17 +207,28 @@ impl BuiltInResult {
156
207
. err_ty
157
208
. convert_swift_expression_to_ffi_type ( "err" , type_pos) ;
158
209
159
- format ! (
160
- "{{ switch {val} {{ case .Ok(let ok): return __private__ResultPtrAndPtr(is_ok: true, ok_or_err: {convert_ok}) case .Err(let err): return __private__ResultPtrAndPtr(is_ok: false, ok_or_err: {convert_err}) }} }}()" ,
161
- val = expression
162
- )
210
+ if self . ok_ty . can_be_encoded_with_zero_bytes ( ) {
211
+ format ! (
212
+ "{{ switch {val} {{ case .Ok(let ok): return __private__ResultVoidAndPtr(is_ok: true, err: nil) case .Err(let err): return __private__ResultVoidAndPtr(is_ok: false, err: {convert_err}) }} }}()" ,
213
+ val = expression
214
+ )
215
+ } else {
216
+ format ! (
217
+ "{{ switch {val} {{ case .Ok(let ok): return __private__ResultPtrAndPtr(is_ok: true, ok_or_err: {convert_ok}) case .Err(let err): return __private__ResultPtrAndPtr(is_ok: false, ok_or_err: {convert_err}) }} }}()" ,
218
+ val = expression
219
+ )
220
+ }
163
221
}
164
222
165
223
pub fn to_c ( & self ) -> & ' static str {
166
224
// TODO: Choose the kind of Result representation based on whether or not the ok and error
167
225
// types are primitives.
168
226
// See `swift-bridge/src/std_bridge/result`
169
- "struct __private__ResultPtrAndPtr"
227
+ if self . ok_ty . can_be_encoded_with_zero_bytes ( ) {
228
+ "struct __private__ResultVoidAndPtr"
229
+ } else {
230
+ "struct __private__ResultPtrAndPtr"
231
+ }
170
232
}
171
233
}
172
234
0 commit comments