Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change how mutability in msg_send! is done #150

Merged
merged 7 commits into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions objc2-foundation/examples/custom_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,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());
}
17 changes: 10 additions & 7 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,18 @@ impl<T: Message, O: Ownership> NSMutableArray<T, O> {
obj
}

fn remove_last(&mut self) {
unsafe { msg_send![self, removeLastObject] }
}

#[doc(alias = "removeLastObject")]
pub fn pop(&mut self) -> Option<Id<T, O>> {
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| {
self.remove_last();
obj
})
}

#[doc(alias = "removeAllObjects")]
Expand Down
7 changes: 5 additions & 2 deletions objc2-foundation/src/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,14 @@ mod tests {
let s2 = s1.copy();
// NSAttributedString performs this optimization in GNUStep's runtime,
// but not in Apple's; so we don't test for it!
// assert_eq!(s1.as_ptr(), s2.as_ptr());
// assert_eq!(Id::as_ptr(&s1), Id::as_ptr(&s2));
assert!(s2.is_kind_of(NSAttributedString::class()));

let s3 = s1.mutable_copy();
assert_ne!(s1.as_ptr(), s3.as_ptr() as *mut NSAttributedString);
assert_ne!(
Id::as_ptr(&s1),
Id::as_ptr(&s3) as *const NSAttributedString
);
assert!(s3.is_kind_of(NSMutableAttributedString::class()));
}
}
7 changes: 6 additions & 1 deletion objc2-foundation/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,14 @@ impl NSMutableData {

/// Mutation methods
impl NSMutableData {
// Helps with reborrowing issue
fn raw_bytes_mut(&mut self) -> *mut c_void {
unsafe { msg_send![self, mutableBytes] }
}

#[doc(alias = "mutableBytes")]
pub fn bytes_mut(&mut self) -> &mut [u8] {
let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
let ptr = self.raw_bytes_mut();
// The bytes pointer may be null for length zero
if ptr.is_null() {
&mut []
Expand Down
2 changes: 1 addition & 1 deletion objc2-foundation/src/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<K: Message, V: Message> NSDictionary<K, V> {

pub fn into_values_array(dict: Id<Self, Owned>) -> Id<NSArray<V, Owned>, Shared> {
unsafe {
let vals = msg_send![dict, allValues];
let vals = msg_send![&dict, allValues];
Id::retain_autoreleased(vals).unwrap()
}
}
Expand Down
2 changes: 1 addition & 1 deletion objc2-foundation/src/enumerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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] }
}
}

Expand Down
7 changes: 5 additions & 2 deletions objc2-foundation/src/mutable_attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,14 @@ mod tests {
fn test_copy() {
let s1 = NSMutableAttributedString::from_nsstring(&NSString::from_str("abc"));
let s2 = s1.copy();
assert_ne!(s1.as_ptr() as *const NSAttributedString, s2.as_ptr());
assert_ne!(
Id::as_ptr(&s1) as *const NSAttributedString,
Id::as_ptr(&s2)
);
assert!(s2.is_kind_of(NSAttributedString::class()));

let s3 = s1.mutable_copy();
assert_ne!(s1.as_ptr(), s3.as_ptr());
assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3));
assert!(s3.is_kind_of(NSMutableAttributedString::class()));
}
}
4 changes: 2 additions & 2 deletions objc2-foundation/src/mutable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,11 @@ mod tests {
fn test_copy() {
let s1 = NSMutableString::from_str("abc");
let s2 = s1.copy();
assert_ne!(s1.as_ptr(), s2.as_ptr() as *mut NSMutableString);
assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s2) as *const NSMutableString);
assert!(s2.is_kind_of(NSString::class()));

let s3 = s1.mutable_copy();
assert_ne!(s1.as_ptr(), s3.as_ptr());
assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3));
assert!(s3.is_kind_of(NSMutableString::class()));
}
}
4 changes: 2 additions & 2 deletions objc2-foundation/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,11 @@ mod tests {
let s1 = NSString::from_str("abc");
let s2 = s1.copy();
// An optimization that NSString makes, since it is immutable
assert_eq!(s1.as_ptr(), s2.as_ptr());
assert_eq!(Id::as_ptr(&s1), Id::as_ptr(&s2));
assert!(s2.is_kind_of(NSString::class()));

let s3 = s1.mutable_copy();
assert_ne!(s1.as_ptr(), s3.as_ptr() as *mut NSString);
assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3) as *const NSString);
assert!(s3.is_kind_of(NSMutableString::class()));
}

Expand Down
2 changes: 1 addition & 1 deletion objc2-foundation/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(feature = "gnustep-1-7"))]
Expand Down
22 changes: 21 additions & 1 deletion objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
upgrading easier.
* Allow using `From`/`TryFrom` to convert between `rc::Id` and `rc::WeakId`.
* Added `Bool::as_bool` (more descriptive name than `Bool::is_true`).
* Added convenience method `Id::as_ptr`.
* Added convenience method `Id::as_ptr` and `Id::as_mut_ptr`.
* The `objc2-encode` dependency is now exposed as `objc2::encode`.
* Added `Id::retain_autoreleased` to allow following Cocoas memory management
rules more efficiently.
Expand All @@ -38,6 +38,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
`ClassBuilder::add_method`.
* Renamed `ClassDecl` and `ProtocolDecl` to `ClassBuilder` and
`ProtocolBuilder`. The old names are kept as deprecated aliases.
* **BREAKING**: Changed how `msg_send!` works wrt. capturing its arguments.

This will require changes to your code wherever you used `Id`, for example:
```rust
// Before
let obj: Id<Object, Owned> = ...;
let p: i32 = unsafe { msg_send![obj, parameter] };
let _: () = unsafe { msg_send![obj, setParameter: p + 1] };
// After
let mut obj: Id<Object, Owned> = ...;
let p: i32 = unsafe { msg_send![&obj, parameter] };
let _: () = unsafe { msg_send![&mut obj, setParameter: p + 1] };
```

Notice that we now clearly pass `obj` by reference, and therein also
communicate the mutability of the object (in the first case, immutable, and
in the second, mutable).

If you previously used `*mut Object` or `&Object` as the receiver, message
sending should work exactly as before.

### Fixed
* Properly sealed the `MessageArguments` trait (it already had a hidden
Expand Down
20 changes: 10 additions & 10 deletions objc2/benches/autorelease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ fn new_nsdata() -> Id<Object, Shared> {
unsafe { Id::new(obj).unwrap_unchecked() }
}

fn new_leaked_nsdata() -> *mut Object {
ManuallyDrop::new(new_nsdata()).as_ptr()
fn new_leaked_nsdata() -> *const Object {
Id::as_ptr(&*ManuallyDrop::new(new_nsdata()))
}

fn autoreleased_nsdata() -> *mut Object {
fn autoreleased_nsdata() -> *const Object {
// let bytes_ptr = BYTES.as_ptr() as *const c_void;
// unsafe {
// msg_send![
Expand All @@ -83,20 +83,20 @@ fn new_nsstring() -> Id<Object, Shared> {
unsafe { Id::new(obj).unwrap_unchecked() }
}

fn new_leaked_nsstring() -> *mut Object {
ManuallyDrop::new(new_nsstring()).as_ptr()
fn new_leaked_nsstring() -> *const Object {
Id::as_ptr(&*ManuallyDrop::new(new_nsstring()))
}

fn autoreleased_nsstring() -> *mut Object {
fn autoreleased_nsstring() -> *const Object {
// unsafe { msg_send![class!(NSString), string] }
unsafe { msg_send![new_leaked_nsstring(), autorelease] }
}

fn retain_autoreleased(obj: *mut Object) -> Id<Object, Shared> {
unsafe { Id::retain_autoreleased(obj.cast()).unwrap_unchecked() }
fn retain_autoreleased(obj: *const Object) -> Id<Object, Shared> {
unsafe { Id::retain_autoreleased((obj as *mut Object).cast()).unwrap_unchecked() }
}

fn autoreleased_nsdata_pool_cleanup() -> *mut Object {
fn autoreleased_nsdata_pool_cleanup() -> *const Object {
autoreleasepool(|_| autoreleased_nsdata())
}

Expand All @@ -108,7 +108,7 @@ fn autoreleased_nsdata_fast_caller_cleanup_pool_cleanup() -> Id<Object, Shared>
autoreleasepool(|_| retain_autoreleased(autoreleased_nsdata()))
}

fn autoreleased_nsstring_pool_cleanup() -> *mut Object {
fn autoreleased_nsstring_pool_cleanup() -> *const Object {
autoreleasepool(|_| autoreleased_nsstring())
}

Expand Down
2 changes: 1 addition & 1 deletion objc2/examples/introspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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);
}
8 changes: 4 additions & 4 deletions objc2/examples/talk_to_me.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ fn main() {
let utterance: *mut Object = unsafe { msg_send![utterance, initWithString: &*string] };
let utterance: Id<Object, Owned> = unsafe { Id::new(utterance).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] };
}
6 changes: 3 additions & 3 deletions objc2/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,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);
}

Expand Down
4 changes: 2 additions & 2 deletions objc2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,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);
//! ```
//!
Expand Down
Loading