diff --git a/objc2-foundation/examples/custom_class.rs b/objc2-foundation/examples/custom_class.rs index 140536cd8..d1c370b35 100644 --- a/objc2-foundation/examples/custom_class.rs +++ b/objc2-foundation/examples/custom_class.rs @@ -72,12 +72,12 @@ fn main() { obj.set_number(7); println!("Number: {}", unsafe { - let number: u32 = msg_send![obj, number]; + let number: u32 = msg_send![&obj, number]; number }); unsafe { - let _: () = msg_send![obj, setNumber: 12u32]; + let _: () = msg_send![&mut obj, setNumber: 12u32]; } println!("Number: {}", obj.number()); } diff --git a/objc2-foundation/src/array.rs b/objc2-foundation/src/array.rs index c2fa4c703..b8553ab48 100644 --- a/objc2-foundation/src/array.rs +++ b/objc2-foundation/src/array.rs @@ -274,13 +274,14 @@ impl NSMutableArray { #[doc(alias = "removeLastObject")] pub fn pop(&mut self) -> Option> { - self.last().map(|obj| { - let obj = unsafe { Id::retain(obj as *const T as *mut T).unwrap_unchecked() }; - unsafe { - let _: () = msg_send![self, removeLastObject]; - } - obj - }) + self.last() + .map(|obj| unsafe { Id::retain(obj as *const T as *mut T).unwrap_unchecked() }) + .map(|obj| { + unsafe { + let _: () = msg_send![self, removeLastObject]; + } + obj + }) } #[doc(alias = "removeAllObjects")] diff --git a/objc2-foundation/src/data.rs b/objc2-foundation/src/data.rs index 5b6fa044d..7a922130f 100644 --- a/objc2-foundation/src/data.rs +++ b/objc2-foundation/src/data.rs @@ -156,7 +156,8 @@ impl NSMutableData { impl NSMutableData { #[doc(alias = "mutableBytes")] pub fn bytes_mut(&mut self) -> &mut [u8] { - let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] }; + // Reborrow + let ptr: *mut c_void = unsafe { msg_send![&mut *self, mutableBytes] }; // The bytes pointer may be null for length zero if ptr.is_null() { &mut [] diff --git a/objc2-foundation/src/dictionary.rs b/objc2-foundation/src/dictionary.rs index 072b3190c..69fde1907 100644 --- a/objc2-foundation/src/dictionary.rs +++ b/objc2-foundation/src/dictionary.rs @@ -129,7 +129,7 @@ impl NSDictionary { pub fn into_values_array(dict: Id) -> Id, Shared> { unsafe { - let vals = msg_send![dict, allValues]; + let vals = msg_send![&dict, allValues]; Id::retain_autoreleased(vals).unwrap() } } diff --git a/objc2-foundation/src/enumerator.rs b/objc2-foundation/src/enumerator.rs index 305f4c094..35f2b3776 100644 --- a/objc2-foundation/src/enumerator.rs +++ b/objc2-foundation/src/enumerator.rs @@ -33,7 +33,7 @@ impl<'a, T: Message> Iterator for NSEnumerator<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - unsafe { msg_send![self.id, nextObject] } + unsafe { msg_send![&mut self.id, nextObject] } } } diff --git a/objc2-foundation/src/value.rs b/objc2-foundation/src/value.rs index a79a3f30c..1ada87363 100644 --- a/objc2-foundation/src/value.rs +++ b/objc2-foundation/src/value.rs @@ -177,7 +177,7 @@ mod tests { fn test_value_nsrange() { let val = NSValue::new(NSRange::from(1..2)); assert!(NSRange::ENCODING.equivalent_to_str(val.encoding().unwrap())); - let range: NSRange = unsafe { objc2::msg_send![val, rangeValue] }; + let range: NSRange = unsafe { objc2::msg_send![&val, rangeValue] }; assert_eq!(range, NSRange::from(1..2)); // NSValue -getValue is broken on GNUStep for some types #[cfg(not(gnustep))] diff --git a/objc2/examples/introspection.rs b/objc2/examples/introspection.rs index fa878dd2b..a57018b63 100644 --- a/objc2/examples/introspection.rs +++ b/objc2/examples/introspection.rs @@ -41,6 +41,6 @@ fn main() { } // Invoke a method on the object - let hash: usize = unsafe { msg_send![obj, hash] }; + let hash: usize = unsafe { msg_send![&obj, hash] }; println!("NSObject hash: {}", hash); } diff --git a/objc2/examples/talk_to_me.rs b/objc2/examples/talk_to_me.rs index 14c0aaebe..bdc8a656b 100644 --- a/objc2/examples/talk_to_me.rs +++ b/objc2/examples/talk_to_me.rs @@ -31,9 +31,9 @@ fn main() { let utterance: Id = unsafe { msg_send_id![utterance, initWithString: &*string] }.unwrap(); - // let _: () = unsafe { msg_send![utterance, setVolume: 90.0f32 }; - // let _: () = unsafe { msg_send![utterance, setRate: 0.50f32 }; - // let _: () = unsafe { msg_send![utterance, setPitchMultiplier: 0.80f32 }; + // let _: () = unsafe { msg_send![&utterance, setVolume: 90.0f32 }; + // let _: () = unsafe { msg_send![&utterance, setRate: 0.50f32 }; + // let _: () = unsafe { msg_send![&utterance, setPitchMultiplier: 0.80f32 }; - let _: () = unsafe { msg_send![synthesizer, speakUtterance: &*utterance] }; + let _: () = unsafe { msg_send![&synthesizer, speakUtterance: &*utterance] }; } diff --git a/objc2/src/bool.rs b/objc2/src/bool.rs index 254da59f1..af2fe130a 100644 --- a/objc2/src/bool.rs +++ b/objc2/src/bool.rs @@ -22,7 +22,7 @@ use core::fmt; /// let ns_value: Id = unsafe { /// msg_send_id![class!(NSNumber), numberWithBool: Bool::YES].unwrap() /// }; -/// assert!(unsafe { msg_send_bool![ns_value, boolValue] }); +/// assert!(unsafe { msg_send_bool![&ns_value, boolValue] }); /// ``` #[repr(transparent)] // We don't implement comparison traits because they could be implemented with diff --git a/objc2/src/declare.rs b/objc2/src/declare.rs index 2c2da05d9..e3f2b56ba 100644 --- a/objc2/src/declare.rs +++ b/objc2/src/declare.rs @@ -403,9 +403,9 @@ mod tests { #[test] fn test_custom_class() { // Registering the custom class is in test_utils - let obj = test_utils::custom_object(); - let _: () = unsafe { msg_send![obj, setFoo: 13u32] }; - let result: u32 = unsafe { msg_send![obj, foo] }; + let mut obj = test_utils::custom_object(); + let _: () = unsafe { msg_send![&mut obj, setFoo: 13u32] }; + let result: u32 = unsafe { msg_send![&obj, foo] }; assert_eq!(result, 13); } diff --git a/objc2/src/lib.rs b/objc2/src/lib.rs index 8c2c5a5cd..73787f265 100644 --- a/objc2/src/lib.rs +++ b/objc2/src/lib.rs @@ -41,8 +41,8 @@ //! }; //! //! // Usage -//! let hash: NSUInteger = unsafe { msg_send![obj, hash] }; -//! let is_kind = unsafe { msg_send_bool![obj, isKindOfClass: cls] }; +//! let hash: NSUInteger = unsafe { msg_send![&obj, hash] }; +//! let is_kind = unsafe { msg_send_bool![&obj, isKindOfClass: cls] }; //! assert!(is_kind); //! ``` //! diff --git a/objc2/src/macros.rs b/objc2/src/macros.rs index 58755723d..30780075e 100644 --- a/objc2/src/macros.rs +++ b/objc2/src/macros.rs @@ -179,25 +179,25 @@ macro_rules! msg_send { [super($obj:expr, $superclass:expr), $selector:ident $(,)?] => ({ let sel = $crate::sel!($selector); $crate::__msg_send_inner! { - @call $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ()) + @call $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ()) } }); [super($obj:expr, $superclass:expr), $($selector:ident : $argument:expr $(,)?)+] => ({ let sel = $crate::sel!($($selector :)+); $crate::__msg_send_inner! { - @call $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ($($argument,)+)) + @call $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ($($argument,)+)) } }); [$obj:expr, $selector:ident $(,)?] => ({ let sel = $crate::sel!($selector); $crate::__msg_send_inner! { - @call $crate::MessageReceiver::send_message(&$obj, sel, ()) + @call $crate::MessageReceiver::send_message($obj, sel, ()) } }); [$obj:expr, $($selector:ident : $argument:expr $(,)?)+] => ({ let sel = $crate::sel!($($selector :)+); $crate::__msg_send_inner! { - @call $crate::MessageReceiver::send_message(&$obj, sel, ($($argument,)+)) + @call $crate::MessageReceiver::send_message($obj, sel, ($($argument,)+)) } }); } diff --git a/objc2/src/message/mod.rs b/objc2/src/message/mod.rs index 22494878d..4fa083860 100644 --- a/objc2/src/message/mod.rs +++ b/objc2/src/message/mod.rs @@ -69,19 +69,19 @@ unsafe impl Message for Class {} // TODO: Make this fully private pub(crate) mod private { - use super::{Id, ManuallyDrop, Message, MessageReceiver, NonNull, Ownership}; + use super::*; pub trait Sealed {} impl Sealed for *const T {} impl Sealed for *mut T {} + impl Sealed for NonNull {} impl<'a, T: Message + ?Sized> Sealed for &'a T {} impl<'a, T: Message + ?Sized> Sealed for &'a mut T {} - impl Sealed for NonNull {} - impl Sealed for Id {} - impl Sealed for ManuallyDrop {} + impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a Id {} + impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a mut Id {} } /// Types that can directly be used as the receiver of Objective-C messages. @@ -96,9 +96,9 @@ pub(crate) mod private { /// # Safety /// /// [`Self::as_raw_receiver`] must be implemented correctly. -pub unsafe trait MessageReceiver: private::Sealed { +pub unsafe trait MessageReceiver: private::Sealed + Sized { /// Get a raw pointer to the receiver of the message. - fn as_raw_receiver(&self) -> *mut Object; + fn as_raw_receiver(self) -> *mut Object; /// Sends a message to self with the given selector and arguments. /// @@ -118,7 +118,7 @@ pub unsafe trait MessageReceiver: private::Sealed { /// The added invariant is that the selector must take the same number of /// arguments as is given. #[cfg_attr(not(feature = "verify_message"), inline(always))] - unsafe fn send_message(&self, sel: Sel, args: A) -> Result + unsafe fn send_message(self, sel: Sel, args: A) -> Result where A: MessageArguments, R: Encode, @@ -161,7 +161,7 @@ pub unsafe trait MessageReceiver: private::Sealed { /// arguments as is given. #[cfg_attr(not(feature = "verify_message"), inline(always))] unsafe fn send_super_message( - &self, + self, superclass: &Class, sel: Sel, args: A, @@ -202,7 +202,7 @@ pub unsafe trait MessageReceiver: private::Sealed { /// assert!(result.is_ok()); /// ``` #[cfg(feature = "malloc")] - fn verify_message(&self, sel: Sel) -> Result<(), MessageError> + fn verify_message(self, sel: Sel) -> Result<(), MessageError> where A: EncodeArguments, R: Encode, @@ -217,50 +217,50 @@ pub unsafe trait MessageReceiver: private::Sealed { unsafe impl MessageReceiver for *const T { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - *self as *mut T as *mut Object + fn as_raw_receiver(self) -> *mut Object { + self as *mut T as *mut Object } } unsafe impl MessageReceiver for *mut T { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - *self as *mut Object + fn as_raw_receiver(self) -> *mut Object { + self as *mut Object } } -unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { +unsafe impl MessageReceiver for NonNull { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - *self as *const T as *mut T as *mut Object + fn as_raw_receiver(self) -> *mut Object { + self.as_ptr() as *mut Object } } -unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { +unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - *self as *const T as *mut T as *mut Object + fn as_raw_receiver(self) -> *mut Object { + self as *const T as *mut T as *mut Object } } -unsafe impl MessageReceiver for NonNull { +unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - self.as_ptr() as *mut Object + fn as_raw_receiver(self) -> *mut Object { + self as *const T as *mut T as *mut Object } } -unsafe impl MessageReceiver for Id { +unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id { #[inline] - fn as_raw_receiver(&self) -> *mut Object { + fn as_raw_receiver(self) -> *mut Object { self.as_ptr() as *mut Object } } -unsafe impl MessageReceiver for ManuallyDrop { +unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a mut Id { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - (**self).as_raw_receiver() + fn as_raw_receiver(self) -> *mut Object { + self.as_ptr() as *mut Object } } @@ -382,10 +382,10 @@ mod tests { #[test] fn test_send_message() { - let obj = test_utils::custom_object(); + let mut obj = test_utils::custom_object(); let result: u32 = unsafe { - let _: () = msg_send![obj, setFoo: 4u32]; - msg_send![obj, foo] + let _: () = msg_send![&mut obj, setFoo: 4u32]; + msg_send![&obj, foo] }; assert_eq!(result, 4); } @@ -393,7 +393,7 @@ mod tests { #[test] fn test_send_message_stret() { let obj = test_utils::custom_object(); - let result: test_utils::CustomStruct = unsafe { msg_send![obj, customStruct] }; + let result: test_utils::CustomStruct = unsafe { msg_send![&obj, customStruct] }; let expected = test_utils::CustomStruct { a: 1, b: 2, @@ -406,7 +406,7 @@ mod tests { #[cfg(not(feature = "verify_message"))] #[test] fn test_send_message_nil() { - use crate::rc::Shared; + use crate::rc::{Id, Shared}; let nil: *mut Object = ::core::ptr::null_mut(); @@ -439,15 +439,15 @@ mod tests { #[test] fn test_send_message_super() { - let obj = test_utils::custom_subclass_object(); + let mut obj = test_utils::custom_subclass_object(); let superclass = test_utils::custom_class(); unsafe { - let _: () = msg_send![obj, setFoo: 4u32]; - let foo: u32 = msg_send![super(obj, superclass), foo]; + let _: () = msg_send![&mut obj, setFoo: 4u32]; + let foo: u32 = msg_send![super(&obj, superclass), foo]; assert_eq!(foo, 4); // The subclass is overriden to return foo + 2 - let foo: u32 = msg_send![obj, foo]; + let foo: u32 = msg_send![&obj, foo]; assert_eq!(foo, 6); } } @@ -455,10 +455,10 @@ mod tests { #[test] fn test_send_message_manuallydrop() { let obj = test_utils::custom_object(); - let obj = ManuallyDrop::new(obj); + let mut obj = ManuallyDrop::new(obj); let result: u32 = unsafe { - let _: () = msg_send![obj, setFoo: 4u32]; - msg_send![obj, foo] + let _: () = msg_send![&mut obj, setFoo: 4u32]; + msg_send![&obj, foo] }; assert_eq!(result, 4); diff --git a/objc2/src/rc/alloc.rs b/objc2/src/rc/alloc.rs index 60359f92a..66c92f29d 100644 --- a/objc2/src/rc/alloc.rs +++ b/objc2/src/rc/alloc.rs @@ -49,7 +49,7 @@ impl __MsgSendId<&'_ Class, Option Result, O>>, MessageError> { - unsafe { MessageReceiver::send_message(&cls, sel, args).map(|r| Id::new(r)) } + unsafe { MessageReceiver::send_message(cls, sel, args).map(|r| Id::new(r)) } } #[inline(always)] @@ -60,7 +60,7 @@ impl __MsgSendId<&'_ Class, Option Result, O>>, MessageError> { unsafe { - MessageReceiver::send_super_message(&cls, superclass, sel, args).map(|r| Id::new(r)) + MessageReceiver::send_super_message(cls, superclass, sel, args).map(|r| Id::new(r)) } } } @@ -81,7 +81,7 @@ impl __MsgSendId, O>>, // // We do this for efficiency, to avoid having a branch after every // `alloc`, that the user did not intend. - unsafe { MessageReceiver::send_message(&ptr, sel, args).map(|r| Id::new(r)) } + unsafe { MessageReceiver::send_message(ptr, sel, args).map(|r| Id::new(r)) } } #[inline(always)] @@ -94,7 +94,7 @@ impl __MsgSendId, O>>, let ptr = Id::option_into_ptr(obj); // SAFETY: Same as above unsafe { - MessageReceiver::send_super_message(&ptr, superclass, sel, args).map(|r| Id::new(r)) + MessageReceiver::send_super_message(ptr, superclass, sel, args).map(|r| Id::new(r)) } } } @@ -108,7 +108,7 @@ impl __MsgSendId Result>, MessageError> { - unsafe { MessageReceiver::send_message(&obj, sel, args).map(|r| Id::new(r)) } + unsafe { MessageReceiver::send_message(obj, sel, args).map(|r| Id::new(r)) } } #[inline(always)] @@ -119,7 +119,7 @@ impl __MsgSendId Result>, MessageError> { unsafe { - MessageReceiver::send_super_message(&obj, superclass, sel, args).map(|r| Id::new(r)) + MessageReceiver::send_super_message(obj, superclass, sel, args).map(|r| Id::new(r)) } } } @@ -135,9 +135,7 @@ impl __MsgSendId Result>, MessageError> { // All code between the message send and the `retain_autoreleased` // must be able to be optimized away for this to work. - unsafe { - MessageReceiver::send_message(&obj, sel, args).map(|r| Id::retain_autoreleased(r)) - } + unsafe { MessageReceiver::send_message(obj, sel, args).map(|r| Id::retain_autoreleased(r)) } } #[inline(always)] @@ -150,7 +148,7 @@ impl __MsgSendId(pool: &'p AutoreleasePool) -> &'p mut Object { /// let obj: Id = unsafe { msg_send_id![class!(NSObject), new].unwrap() }; /// let obj = ManuallyDrop::new(obj); -/// let obj: *mut Object = unsafe { msg_send![obj, autorelease] }; +/// let obj: *mut Object = unsafe { msg_send![&*obj, autorelease] }; /// // Lifetime of the returned reference is bounded by the pool /// unsafe { pool.ptr_as_mut(obj) } /// diff --git a/objc2/src/test_utils.rs b/objc2/src/test_utils.rs index 12f44d82a..b779afa09 100644 --- a/objc2/src/test_utils.rs +++ b/objc2/src/test_utils.rs @@ -1,3 +1,4 @@ +use core::mem::ManuallyDrop; use core::ops::{Deref, DerefMut}; use std::os::raw::c_char; use std::sync::Once; @@ -20,12 +21,36 @@ impl CustomObject { } // TODO: Remove the need for this hack -impl crate::message::private::Sealed for CustomObject {} +impl crate::message::private::Sealed for &CustomObject {} +impl crate::message::private::Sealed for &mut CustomObject {} +impl crate::message::private::Sealed for &ManuallyDrop {} +impl crate::message::private::Sealed for &mut ManuallyDrop {} -unsafe impl MessageReceiver for CustomObject { +unsafe impl MessageReceiver for &CustomObject { #[inline] - fn as_raw_receiver(&self) -> *mut Object { - self.obj + fn as_raw_receiver(self) -> *mut Object { + (&**self).as_raw_receiver() + } +} + +unsafe impl MessageReceiver for &mut CustomObject { + #[inline] + fn as_raw_receiver(self) -> *mut Object { + (&**self).as_raw_receiver() + } +} + +unsafe impl MessageReceiver for &ManuallyDrop { + #[inline] + fn as_raw_receiver(self) -> *mut Object { + (&**self).as_raw_receiver() + } +} + +unsafe impl MessageReceiver for &mut ManuallyDrop { + #[inline] + fn as_raw_receiver(self) -> *mut Object { + (&**self).as_raw_receiver() } } diff --git a/tests/assembly/test_msg_send_zero_cost/lib.rs b/tests/assembly/test_msg_send_zero_cost/lib.rs index 9a29a4af4..faf37d5cb 100644 --- a/tests/assembly/test_msg_send_zero_cost/lib.rs +++ b/tests/assembly/test_msg_send_zero_cost/lib.rs @@ -5,5 +5,5 @@ use objc2::MessageReceiver; #[no_mangle] pub fn handle(obj: &Object, sel: Sel) -> *mut Object { - unsafe { MessageReceiver::send_message(&obj, sel, ()).unwrap() } + unsafe { MessageReceiver::send_message(obj, sel, ()).unwrap() } } diff --git a/tests/assembly/test_retain_autoreleased/lib.rs b/tests/assembly/test_retain_autoreleased/lib.rs index 9a722262c..ca1de6623 100644 --- a/tests/assembly/test_retain_autoreleased/lib.rs +++ b/tests/assembly/test_retain_autoreleased/lib.rs @@ -6,6 +6,6 @@ use objc2::MessageReceiver; #[no_mangle] pub fn handle(obj: &Object, sel: Sel) -> Option> { - let ptr: *mut Object = unsafe { MessageReceiver::send_message(&obj, sel, ()).unwrap() }; + let ptr: *mut Object = unsafe { MessageReceiver::send_message(obj, sel, ()).unwrap() }; unsafe { Id::retain_autoreleased(ptr) } }