1
1
use alloc:: string:: { String , ToString } ;
2
2
use core:: fmt;
3
3
use core:: mem;
4
+ use core:: mem:: ManuallyDrop ;
4
5
use core:: ptr:: NonNull ;
5
6
use std:: error:: Error ;
6
7
@@ -57,13 +58,16 @@ use self::verify::{verify_message_signature, VerificationError};
57
58
/// [`objc_msgSend`]: https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend
58
59
pub unsafe trait Message : RefEncode { }
59
60
61
+ // SAFETY: `ManuallyDrop` is `repr(transparent)`.
62
+ unsafe impl < T : Message + ?Sized > Message for ManuallyDrop < T > { }
63
+
60
64
unsafe impl Message for Object { }
61
65
62
66
unsafe impl Message for Class { }
63
67
64
68
// TODO: Make this fully private
65
69
pub ( crate ) mod private {
66
- use super :: { Id , Message , NonNull , Ownership } ;
70
+ use super :: { Id , ManuallyDrop , Message , MessageReceiver , NonNull , Ownership } ;
67
71
68
72
pub trait Sealed { }
69
73
@@ -74,6 +78,8 @@ pub(crate) mod private {
74
78
impl < ' a , T : Message + ?Sized > Sealed for & ' a mut T { }
75
79
impl < T : Message + ?Sized > Sealed for NonNull < T > { }
76
80
impl < T : Message , O : Ownership > Sealed for Id < T , O > { }
81
+
82
+ impl < T : MessageReceiver + ?Sized > Sealed for ManuallyDrop < T > { }
77
83
}
78
84
79
85
/// Types that can directly be used as the receiver of Objective-C messages.
@@ -247,6 +253,13 @@ unsafe impl<T: Message, O: Ownership> MessageReceiver for Id<T, O> {
247
253
}
248
254
}
249
255
256
+ unsafe impl < T : MessageReceiver + ?Sized > MessageReceiver for ManuallyDrop < T > {
257
+ #[ inline]
258
+ fn as_raw_receiver ( & self ) -> * mut Object {
259
+ ( * * self ) . as_raw_receiver ( )
260
+ }
261
+ }
262
+
250
263
/// Types that may be used as the arguments of an Objective-C message.
251
264
///
252
265
/// This is implemented for tuples of up to 12 arguments, where each argument
@@ -419,6 +432,21 @@ mod tests {
419
432
}
420
433
}
421
434
435
+ #[ test]
436
+ fn test_send_message_manuallydrop ( ) {
437
+ let obj = test_utils:: custom_object ( ) ;
438
+ let obj = ManuallyDrop :: new ( obj) ;
439
+ let result: u32 = unsafe {
440
+ let _: ( ) = msg_send ! [ obj, setFoo: 4u32 ] ;
441
+ msg_send ! [ obj, foo]
442
+ } ;
443
+ assert_eq ! ( result, 4 ) ;
444
+
445
+ let obj: * const ManuallyDrop < Object > = ( & * * obj as * const Object ) . cast ( ) ;
446
+ let result: u32 = unsafe { msg_send ! [ obj, foo] } ;
447
+ assert_eq ! ( result, 4 ) ;
448
+ }
449
+
422
450
#[ test]
423
451
fn test_verify_message ( ) {
424
452
let obj = test_utils:: custom_object ( ) ;
0 commit comments