Skip to content

Commit f1edce7

Browse files
committed
Change msg_send! such that callers can properly communicate mutability
1 parent b6b9f9c commit f1edce7

File tree

15 files changed

+98
-71
lines changed

15 files changed

+98
-71
lines changed

objc2-foundation/examples/custom_class.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ fn main() {
7272

7373
obj.set_number(7);
7474
println!("Number: {}", unsafe {
75-
let number: u32 = msg_send![obj, number];
75+
let number: u32 = msg_send![&obj, number];
7676
number
7777
});
7878

7979
unsafe {
80-
let _: () = msg_send![obj, setNumber: 12u32];
80+
let _: () = msg_send![&mut obj, setNumber: 12u32];
8181
}
8282
println!("Number: {}", obj.number());
8383
}

objc2-foundation/src/array.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,14 @@ impl<T: Message, O: Ownership> NSMutableArray<T, O> {
274274

275275
#[doc(alias = "removeLastObject")]
276276
pub fn pop(&mut self) -> Option<Id<T, O>> {
277-
self.last().map(|obj| {
278-
let obj = unsafe { Id::retain(obj as *const T as *mut T).unwrap_unchecked() };
279-
unsafe {
280-
let _: () = msg_send![self, removeLastObject];
281-
}
282-
obj
283-
})
277+
self.last()
278+
.map(|obj| unsafe { Id::retain(obj as *const T as *mut T).unwrap_unchecked() })
279+
.map(|obj| {
280+
unsafe {
281+
let _: () = msg_send![self, removeLastObject];
282+
}
283+
obj
284+
})
284285
}
285286

286287
#[doc(alias = "removeAllObjects")]

objc2-foundation/src/data.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ impl NSMutableData {
156156
impl NSMutableData {
157157
#[doc(alias = "mutableBytes")]
158158
pub fn bytes_mut(&mut self) -> &mut [u8] {
159-
let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
159+
let this = &mut *self; // Reborrow
160+
let ptr: *mut c_void = unsafe { msg_send![this, mutableBytes] };
160161
// The bytes pointer may be null for length zero
161162
if ptr.is_null() {
162163
&mut []

objc2-foundation/src/dictionary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<K: Message, V: Message> NSDictionary<K, V> {
129129

130130
pub fn into_values_array(dict: Id<Self, Owned>) -> Id<NSArray<V, Owned>, Shared> {
131131
unsafe {
132-
let vals = msg_send![dict, allValues];
132+
let vals = msg_send![&dict, allValues];
133133
Id::retain_autoreleased(vals).unwrap()
134134
}
135135
}

objc2-foundation/src/enumerator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'a, T: Message> Iterator for NSEnumerator<'a, T> {
3333
type Item = &'a T;
3434

3535
fn next(&mut self) -> Option<&'a T> {
36-
unsafe { msg_send![self.id, nextObject] }
36+
unsafe { msg_send![&mut self.id, nextObject] }
3737
}
3838
}
3939

objc2-foundation/src/value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ mod tests {
177177
fn test_value_nsrange() {
178178
let val = NSValue::new(NSRange::from(1..2));
179179
assert!(NSRange::ENCODING.equivalent_to_str(val.encoding().unwrap()));
180-
let range: NSRange = unsafe { objc2::msg_send![val, rangeValue] };
180+
let range: NSRange = unsafe { objc2::msg_send![&val, rangeValue] };
181181
assert_eq!(range, NSRange::from(1..2));
182182
// NSValue -getValue is broken on GNUStep for some types
183183
#[cfg(not(feature = "gnustep-1-7"))]

objc2/examples/introspection.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ fn main() {
4242
}
4343

4444
// Invoke a method on the object
45-
let hash: usize = unsafe { msg_send![obj, hash] };
45+
let hash: usize = unsafe { msg_send![&obj, hash] };
4646
println!("NSObject hash: {}", hash);
4747
}

objc2/examples/talk_to_me.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ fn main() {
3131
let utterance: *mut Object = unsafe { msg_send![utterance, initWithString: &*string] };
3232
let utterance: Id<Object, Owned> = unsafe { Id::new(utterance).unwrap() };
3333

34-
// let _: () = unsafe { msg_send![utterance, setVolume: 90.0f32 };
35-
// let _: () = unsafe { msg_send![utterance, setRate: 0.50f32 };
36-
// let _: () = unsafe { msg_send![utterance, setPitchMultiplier: 0.80f32 };
34+
// let _: () = unsafe { msg_send![&utterance, setVolume: 90.0f32 };
35+
// let _: () = unsafe { msg_send![&utterance, setRate: 0.50f32 };
36+
// let _: () = unsafe { msg_send![&utterance, setPitchMultiplier: 0.80f32 };
3737

38-
let _: () = unsafe { msg_send![synthesizer, speakUtterance: &*utterance] };
38+
let _: () = unsafe { msg_send![&synthesizer, speakUtterance: &*utterance] };
3939
}

objc2/src/declare.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,9 @@ mod tests {
403403
#[test]
404404
fn test_custom_class() {
405405
// Registering the custom class is in test_utils
406-
let obj = test_utils::custom_object();
407-
let _: () = unsafe { msg_send![obj, setFoo: 13u32] };
408-
let result: u32 = unsafe { msg_send![obj, foo] };
406+
let mut obj = test_utils::custom_object();
407+
let _: () = unsafe { msg_send![&mut obj, setFoo: 13u32] };
408+
let result: u32 = unsafe { msg_send![&obj, foo] };
409409
assert_eq!(result, 13);
410410
}
411411

objc2/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
//! };
4343
//!
4444
//! // Usage
45-
//! let hash: NSUInteger = unsafe { msg_send![obj, hash] };
46-
//! let is_kind = unsafe { msg_send_bool![obj, isKindOfClass: cls] };
45+
//! let hash: NSUInteger = unsafe { msg_send![&obj, hash] };
46+
//! let is_kind = unsafe { msg_send_bool![&obj, isKindOfClass: cls] };
4747
//! assert!(is_kind);
4848
//! ```
4949
//!

objc2/src/macros.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ macro_rules! msg_send {
132132
[super($obj:expr, $superclass:expr), $selector:ident $(,)?] => ({
133133
let sel = $crate::sel!($selector);
134134
let result;
135-
match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ()) {
135+
match $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ()) {
136136
Err(s) => panic!("{}", s),
137137
Ok(r) => result = r,
138138
}
@@ -141,7 +141,7 @@ macro_rules! msg_send {
141141
[super($obj:expr, $superclass:expr), $($selector:ident : $argument:expr $(,)?)+] => ({
142142
let sel = $crate::sel!($($selector :)+);
143143
let result;
144-
match $crate::MessageReceiver::send_super_message(&$obj, $superclass, sel, ($($argument,)+)) {
144+
match $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ($($argument,)+)) {
145145
Err(s) => panic!("{}", s),
146146
Ok(r) => result = r,
147147
}
@@ -150,7 +150,7 @@ macro_rules! msg_send {
150150
[$obj:expr, $selector:ident $(,)?] => ({
151151
let sel = $crate::sel!($selector);
152152
let result;
153-
match $crate::MessageReceiver::send_message(&$obj, sel, ()) {
153+
match $crate::MessageReceiver::send_message($obj, sel, ()) {
154154
Err(s) => panic!("{}", s),
155155
Ok(r) => result = r,
156156
}
@@ -159,7 +159,7 @@ macro_rules! msg_send {
159159
[$obj:expr, $($selector:ident : $argument:expr $(,)?)+] => ({
160160
let sel = $crate::sel!($($selector :)+);
161161
let result;
162-
match $crate::MessageReceiver::send_message(&$obj, sel, ($($argument,)+)) {
162+
match $crate::MessageReceiver::send_message($obj, sel, ($($argument,)+)) {
163163
Err(s) => panic!("{}", s),
164164
Ok(r) => result = r,
165165
}

objc2/src/message/mod.rs

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,19 @@ unsafe impl Message for Class {}
6969

7070
// TODO: Make this fully private
7171
pub(crate) mod private {
72-
use super::{Id, ManuallyDrop, Message, MessageReceiver, NonNull, Ownership};
72+
use super::*;
7373

7474
pub trait Sealed {}
7575

7676
impl<T: Message + ?Sized> Sealed for *const T {}
7777
impl<T: Message + ?Sized> Sealed for *mut T {}
78+
impl<T: Message + ?Sized> Sealed for NonNull<T> {}
7879

7980
impl<'a, T: Message + ?Sized> Sealed for &'a T {}
8081
impl<'a, T: Message + ?Sized> Sealed for &'a mut T {}
81-
impl<T: Message + ?Sized> Sealed for NonNull<T> {}
82-
impl<T: Message + ?Sized, O: Ownership> Sealed for Id<T, O> {}
8382

84-
impl<T: MessageReceiver + ?Sized> Sealed for ManuallyDrop<T> {}
83+
impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a Id<T, O> {}
84+
impl<'a, T: Message + ?Sized, O: Ownership> Sealed for &'a mut Id<T, O> {}
8585
}
8686

8787
/// Types that can directly be used as the receiver of Objective-C messages.
@@ -96,9 +96,9 @@ pub(crate) mod private {
9696
/// # Safety
9797
///
9898
/// [`Self::as_raw_receiver`] must be implemented correctly.
99-
pub unsafe trait MessageReceiver: private::Sealed {
99+
pub unsafe trait MessageReceiver: private::Sealed + Sized {
100100
/// Get a raw pointer to the receiver of the message.
101-
fn as_raw_receiver(&self) -> *mut Object;
101+
fn as_raw_receiver(self) -> *mut Object;
102102

103103
/// Sends a message to self with the given selector and arguments.
104104
///
@@ -118,7 +118,7 @@ pub unsafe trait MessageReceiver: private::Sealed {
118118
/// The added invariant is that the selector must take the same number of
119119
/// arguments as is given.
120120
#[cfg_attr(not(feature = "verify_message"), inline(always))]
121-
unsafe fn send_message<A, R>(&self, sel: Sel, args: A) -> Result<R, MessageError>
121+
unsafe fn send_message<A, R>(self, sel: Sel, args: A) -> Result<R, MessageError>
122122
where
123123
A: MessageArguments,
124124
R: Encode,
@@ -161,7 +161,7 @@ pub unsafe trait MessageReceiver: private::Sealed {
161161
/// arguments as is given.
162162
#[cfg_attr(not(feature = "verify_message"), inline(always))]
163163
unsafe fn send_super_message<A, R>(
164-
&self,
164+
self,
165165
superclass: &Class,
166166
sel: Sel,
167167
args: A,
@@ -202,7 +202,7 @@ pub unsafe trait MessageReceiver: private::Sealed {
202202
/// assert!(result.is_ok());
203203
/// ```
204204
#[cfg(feature = "malloc")]
205-
fn verify_message<A, R>(&self, sel: Sel) -> Result<(), MessageError>
205+
fn verify_message<A, R>(self, sel: Sel) -> Result<(), MessageError>
206206
where
207207
A: EncodeArguments,
208208
R: Encode,
@@ -217,50 +217,50 @@ pub unsafe trait MessageReceiver: private::Sealed {
217217

218218
unsafe impl<T: Message + ?Sized> MessageReceiver for *const T {
219219
#[inline]
220-
fn as_raw_receiver(&self) -> *mut Object {
221-
*self as *mut T as *mut Object
220+
fn as_raw_receiver(self) -> *mut Object {
221+
self as *mut T as *mut Object
222222
}
223223
}
224224

225225
unsafe impl<T: Message + ?Sized> MessageReceiver for *mut T {
226226
#[inline]
227-
fn as_raw_receiver(&self) -> *mut Object {
228-
*self as *mut Object
227+
fn as_raw_receiver(self) -> *mut Object {
228+
self as *mut Object
229229
}
230230
}
231231

232-
unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T {
232+
unsafe impl<T: Message + ?Sized> MessageReceiver for NonNull<T> {
233233
#[inline]
234-
fn as_raw_receiver(&self) -> *mut Object {
235-
*self as *const T as *mut T as *mut Object
234+
fn as_raw_receiver(self) -> *mut Object {
235+
self.as_ptr() as *mut Object
236236
}
237237
}
238238

239-
unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T {
239+
unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T {
240240
#[inline]
241-
fn as_raw_receiver(&self) -> *mut Object {
242-
*self as *const T as *mut T as *mut Object
241+
fn as_raw_receiver(self) -> *mut Object {
242+
self as *const T as *mut T as *mut Object
243243
}
244244
}
245245

246-
unsafe impl<T: Message + ?Sized> MessageReceiver for NonNull<T> {
246+
unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T {
247247
#[inline]
248-
fn as_raw_receiver(&self) -> *mut Object {
249-
self.as_ptr() as *mut Object
248+
fn as_raw_receiver(self) -> *mut Object {
249+
self as *const T as *mut T as *mut Object
250250
}
251251
}
252252

253-
unsafe impl<T: Message + ?Sized, O: Ownership> MessageReceiver for Id<T, O> {
253+
unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id<T, O> {
254254
#[inline]
255-
fn as_raw_receiver(&self) -> *mut Object {
255+
fn as_raw_receiver(self) -> *mut Object {
256256
self.as_ptr() as *mut Object
257257
}
258258
}
259259

260-
unsafe impl<T: MessageReceiver + ?Sized> MessageReceiver for ManuallyDrop<T> {
260+
unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a mut Id<T, O> {
261261
#[inline]
262-
fn as_raw_receiver(&self) -> *mut Object {
263-
(**self).as_raw_receiver()
262+
fn as_raw_receiver(self) -> *mut Object {
263+
self.as_ptr() as *mut Object
264264
}
265265
}
266266

@@ -382,18 +382,18 @@ mod tests {
382382

383383
#[test]
384384
fn test_send_message() {
385-
let obj = test_utils::custom_object();
385+
let mut obj = test_utils::custom_object();
386386
let result: u32 = unsafe {
387-
let _: () = msg_send![obj, setFoo: 4u32];
388-
msg_send![obj, foo]
387+
let _: () = msg_send![&mut obj, setFoo: 4u32];
388+
msg_send![&obj, foo]
389389
};
390390
assert_eq!(result, 4);
391391
}
392392

393393
#[test]
394394
fn test_send_message_stret() {
395395
let obj = test_utils::custom_object();
396-
let result: test_utils::CustomStruct = unsafe { msg_send![obj, customStruct] };
396+
let result: test_utils::CustomStruct = unsafe { msg_send![&obj, customStruct] };
397397
let expected = test_utils::CustomStruct {
398398
a: 1,
399399
b: 2,
@@ -431,26 +431,26 @@ mod tests {
431431

432432
#[test]
433433
fn test_send_message_super() {
434-
let obj = test_utils::custom_subclass_object();
434+
let mut obj = test_utils::custom_subclass_object();
435435
let superclass = test_utils::custom_class();
436436
unsafe {
437-
let _: () = msg_send![obj, setFoo: 4u32];
438-
let foo: u32 = msg_send![super(obj, superclass), foo];
437+
let _: () = msg_send![&mut obj, setFoo: 4u32];
438+
let foo: u32 = msg_send![super(&obj, superclass), foo];
439439
assert_eq!(foo, 4);
440440

441441
// The subclass is overriden to return foo + 2
442-
let foo: u32 = msg_send![obj, foo];
442+
let foo: u32 = msg_send![&obj, foo];
443443
assert_eq!(foo, 6);
444444
}
445445
}
446446

447447
#[test]
448448
fn test_send_message_manuallydrop() {
449449
let obj = test_utils::custom_object();
450-
let obj = ManuallyDrop::new(obj);
450+
let mut obj = ManuallyDrop::new(obj);
451451
let result: u32 = unsafe {
452-
let _: () = msg_send![obj, setFoo: 4u32];
453-
msg_send![obj, foo]
452+
let _: () = msg_send![&mut obj, setFoo: 4u32];
453+
msg_send![&obj, foo]
454454
};
455455
assert_eq!(result, 4);
456456

objc2/src/test_utils.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::mem::ManuallyDrop;
12
use core::ops::{Deref, DerefMut};
23
use std::os::raw::c_char;
34
use std::sync::Once;
@@ -20,12 +21,36 @@ impl CustomObject {
2021
}
2122

2223
// TODO: Remove the need for this hack
23-
impl crate::message::private::Sealed for CustomObject {}
24+
impl crate::message::private::Sealed for &CustomObject {}
25+
impl crate::message::private::Sealed for &mut CustomObject {}
26+
impl crate::message::private::Sealed for &ManuallyDrop<CustomObject> {}
27+
impl crate::message::private::Sealed for &mut ManuallyDrop<CustomObject> {}
2428

25-
unsafe impl MessageReceiver for CustomObject {
29+
unsafe impl MessageReceiver for &CustomObject {
2630
#[inline]
27-
fn as_raw_receiver(&self) -> *mut Object {
28-
self.obj
31+
fn as_raw_receiver(self) -> *mut Object {
32+
(&**self).as_raw_receiver()
33+
}
34+
}
35+
36+
unsafe impl MessageReceiver for &mut CustomObject {
37+
#[inline]
38+
fn as_raw_receiver(self) -> *mut Object {
39+
(&**self).as_raw_receiver()
40+
}
41+
}
42+
43+
unsafe impl MessageReceiver for &ManuallyDrop<CustomObject> {
44+
#[inline]
45+
fn as_raw_receiver(self) -> *mut Object {
46+
(&**self).as_raw_receiver()
47+
}
48+
}
49+
50+
unsafe impl MessageReceiver for &mut ManuallyDrop<CustomObject> {
51+
#[inline]
52+
fn as_raw_receiver(self) -> *mut Object {
53+
(&**self).as_raw_receiver()
2954
}
3055
}
3156

tests/assembly/test_msg_send_zero_cost/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ use objc2::MessageReceiver;
55

66
#[no_mangle]
77
pub fn handle(obj: &Object, sel: Sel) -> *mut Object {
8-
unsafe { MessageReceiver::send_message(&obj, sel, ()).unwrap() }
8+
unsafe { MessageReceiver::send_message(obj, sel, ()).unwrap() }
99
}

0 commit comments

Comments
 (0)