diff --git a/objc2-foundation/src/attributed_string.rs b/objc2-foundation/src/attributed_string.rs index f5dd4d9bb..1417f5805 100644 --- a/objc2-foundation/src/attributed_string.rs +++ b/objc2-foundation/src/attributed_string.rs @@ -157,7 +157,10 @@ mod tests { assert!(s2.is_kind_of(NSAttributedString::class())); let s3 = s1.mutable_copy(); - assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3) as *mut NSAttributedString); + assert_ne!( + Id::as_ptr(&s1), + Id::as_ptr(&s3) as *const NSAttributedString + ); assert!(s3.is_kind_of(NSMutableAttributedString::class())); } } diff --git a/objc2-foundation/src/mutable_attributed_string.rs b/objc2-foundation/src/mutable_attributed_string.rs index 8d407115a..77100dee9 100644 --- a/objc2-foundation/src/mutable_attributed_string.rs +++ b/objc2-foundation/src/mutable_attributed_string.rs @@ -90,7 +90,10 @@ mod tests { fn test_copy() { let s1 = NSMutableAttributedString::from_nsstring(&NSString::from_str("abc")); let s2 = s1.copy(); - assert_ne!(Id::as_ptr(&s1) as *mut NSAttributedString, Id::as_ptr(&s2)); + 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(); diff --git a/objc2-foundation/src/mutable_string.rs b/objc2-foundation/src/mutable_string.rs index 46a7973ea..d12e49eb6 100644 --- a/objc2-foundation/src/mutable_string.rs +++ b/objc2-foundation/src/mutable_string.rs @@ -200,7 +200,7 @@ mod tests { fn test_copy() { let s1 = NSMutableString::from_str("abc"); let s2 = s1.copy(); - assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s2) 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(); diff --git a/objc2-foundation/src/string.rs b/objc2-foundation/src/string.rs index e9459c67c..7c5660a46 100644 --- a/objc2-foundation/src/string.rs +++ b/objc2-foundation/src/string.rs @@ -350,7 +350,7 @@ mod tests { assert!(s2.is_kind_of(NSString::class())); let s3 = s1.mutable_copy(); - assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3) as *mut NSString); + assert_ne!(Id::as_ptr(&s1), Id::as_ptr(&s3) as *const NSString); assert!(s3.is_kind_of(NSMutableString::class())); } diff --git a/objc2/CHANGELOG.md b/objc2/CHANGELOG.md index a01897653..13e73e5ce 100644 --- a/objc2/CHANGELOG.md +++ b/objc2/CHANGELOG.md @@ -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. diff --git a/objc2/benches/autorelease.rs b/objc2/benches/autorelease.rs index 5e0ae9ef3..7bb047d16 100644 --- a/objc2/benches/autorelease.rs +++ b/objc2/benches/autorelease.rs @@ -61,11 +61,11 @@ fn new_nsdata() -> Id { unsafe { Id::new(obj).unwrap_unchecked() } } -fn new_leaked_nsdata() -> *mut Object { +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![ @@ -83,20 +83,20 @@ fn new_nsstring() -> Id { unsafe { Id::new(obj).unwrap_unchecked() } } -fn new_leaked_nsstring() -> *mut Object { +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 { - unsafe { Id::retain_autoreleased(obj.cast()).unwrap_unchecked() } +fn retain_autoreleased(obj: *const Object) -> Id { + 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()) } @@ -108,7 +108,7 @@ fn autoreleased_nsdata_fast_caller_cleanup_pool_cleanup() -> Id autoreleasepool(|_| retain_autoreleased(autoreleased_nsdata())) } -fn autoreleased_nsstring_pool_cleanup() -> *mut Object { +fn autoreleased_nsstring_pool_cleanup() -> *const Object { autoreleasepool(|_| autoreleased_nsstring()) } diff --git a/objc2/src/message/mod.rs b/objc2/src/message/mod.rs index 6a6a073e0..3ea1c390d 100644 --- a/objc2/src/message/mod.rs +++ b/objc2/src/message/mod.rs @@ -263,7 +263,7 @@ unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id MessageReceiver for &'a mut Id { #[inline] fn as_raw_receiver(self) -> *mut Object { - Id::as_ptr(self) as *mut Object + Id::as_mut_ptr(self) as *mut Object } } @@ -277,7 +277,7 @@ unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Manua unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut ManuallyDrop> { #[inline] fn as_raw_receiver(self) -> *mut Object { - Id::as_ptr(&mut **self) as *mut Object + Id::as_mut_ptr(&mut **self) as *mut Object } } diff --git a/objc2/src/rc/id.rs b/objc2/src/rc/id.rs index 397b517b5..dbf3bb7ad 100644 --- a/objc2/src/rc/id.rs +++ b/objc2/src/rc/id.rs @@ -192,9 +192,26 @@ impl Id { /// /// The pointer is valid for at least as long as the `Id` is held. /// + /// See [`Id::as_mut_ptr`] for the mutable equivalent. + /// /// This is an associated method, and must be called as `Id::as_ptr(obj)`. #[inline] - pub fn as_ptr(this: &Id) -> *mut T { + pub fn as_ptr(this: &Id) -> *const T { + this.ptr.as_ptr() + } +} + +impl Id { + /// Returns a raw mutable pointer to the object. + /// + /// The pointer is valid for at least as long as the `Id` is held. + /// + /// See [`Id::as_ptr`] for the immutable equivalent. + /// + /// This is an associated method, and must be called as + /// `Id::as_mut_ptr(obj)`. + #[inline] + pub fn as_mut_ptr(this: &mut Id) -> *mut T { this.ptr.as_ptr() } } diff --git a/objc2/src/rc/weak_id.rs b/objc2/src/rc/weak_id.rs index 973b9cd69..c5332dd6a 100644 --- a/objc2/src/rc/weak_id.rs +++ b/objc2/src/rc/weak_id.rs @@ -49,10 +49,10 @@ impl WeakId { /// # Safety /// /// The object must be valid or null. - unsafe fn new_inner(obj: *mut T) -> Self { + unsafe fn new_inner(obj: *const T) -> Self { let inner = Box::new(UnsafeCell::new(ptr::null_mut())); // SAFETY: `ptr` will never move, and the caller verifies `obj` - let _ = unsafe { ffi::objc_initWeak(inner.get(), obj as *mut ffi::objc_object) }; + let _ = unsafe { ffi::objc_initWeak(inner.get(), obj as *mut T as *mut ffi::objc_object) }; Self { inner, item: PhantomData, @@ -108,7 +108,7 @@ impl Default for WeakId { #[inline] fn default() -> Self { // SAFETY: The pointer is null - unsafe { Self::new_inner(ptr::null_mut()) } + unsafe { Self::new_inner(ptr::null()) } } } diff --git a/tests/src/test_object.rs b/tests/src/test_object.rs index 4e9c598a6..46d9d4a1d 100644 --- a/tests/src/test_object.rs +++ b/tests/src/test_object.rs @@ -179,12 +179,12 @@ fn test_object() { assert!(obj.var3().is_null()); assert!(obj.var3_ivar().is_null()); - let obj2 = Id::as_ptr(&mut *ManuallyDrop::new(NSObject::new())).cast::(); + let obj2 = Id::as_mut_ptr(&mut *ManuallyDrop::new(NSObject::new())).cast::(); obj.set_var3(obj2); assert_eq!(obj.var3(), obj2); assert_eq!(*obj.var3_ivar(), obj2); - let obj3 = Id::as_ptr(&mut *ManuallyDrop::new(NSObject::new())).cast::(); + let obj3 = Id::as_mut_ptr(&mut *ManuallyDrop::new(NSObject::new())).cast::(); *obj.var3_ivar_mut() = obj3; assert_ne!(obj.var3(), obj2); assert_ne!(*obj.var3_ivar(), obj2);