@@ -154,6 +154,15 @@ mod msg_send_primitive {
154
154
args : A ,
155
155
) -> R {
156
156
let msg_send_fn = R :: MSG_SEND ;
157
+ // Note: Modern Objective-C compilers have a workaround to ensure that
158
+ // messages to `nil` with a struct return produces `mem::zeroed()`,
159
+ // see:
160
+ // <https://www.sealiesoftware.com/blog/archive/2012/2/29/objc_explain_return_value_of_message_to_nil.html>
161
+ //
162
+ // We _could_ technically do something similar, but since we're
163
+ // disallowing messages to `nil` with `debug_assertions` enabled
164
+ // anyhow, and since Rust has a much stronger type-system that
165
+ // disallows NULL/nil in most cases, we won't bother supporting it.
157
166
unsafe { A :: __invoke ( msg_send_fn, receiver, sel, args) }
158
167
}
159
168
@@ -206,13 +215,21 @@ mod msg_send_primitive {
206
215
sel : Sel ,
207
216
args : A ,
208
217
) -> R {
209
- // If `receiver` is NULL, objc_msg_lookup will return a standard C-method
210
- // taking two arguments, the receiver and the selector. Transmuting and
211
- // calling such a function with multiple parameters is UB, so instead we
212
- // return NULL directly.
218
+ // If `receiver` is NULL, objc_msg_lookup will return a standard
219
+ // C-method taking two arguments, the receiver and the selector.
220
+ //
221
+ // Transmuting and calling such a function with multiple parameters is
222
+ // safe as long as the return value is a primitive (and e.g. not a big
223
+ // struct or array).
224
+ //
225
+ // However, when the return value is a floating point value, the float
226
+ // will end up as some undefined value, usually NaN, which is
227
+ // incompatible with Apple's platforms. As such, we insert this extra
228
+ // NULL check here.
213
229
if receiver. is_null ( ) {
214
230
// SAFETY: Caller guarantees that messages to NULL-receivers only
215
- // return pointers, and a mem::zeroed pointer is just a NULL-pointer.
231
+ // return pointers or primitive values, and a mem::zeroed pointer
232
+ // / primitive is just a NULL-pointer or a zeroed primitive.
216
233
return unsafe { mem:: zeroed ( ) } ;
217
234
}
218
235
0 commit comments