Skip to content

Commit 76e0386

Browse files
committed
Implement IsIdCloneable for AnyObject
1 parent 8baf5d9 commit 76e0386

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

crates/icrate/tests/array.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#![cfg(feature = "Foundation_NSArray")]
22
#![cfg(feature = "Foundation_NSNumber")]
3+
use core::ptr;
4+
35
use icrate::Foundation::{NSArray, NSNumber, NSObject};
46
use objc2::mutability::IsRetainable;
57
use objc2::rc::{Id, __RcTestObject, __ThreadTestData};
6-
use objc2::runtime::ProtocolObject;
8+
use objc2::runtime::{AnyObject, ProtocolObject};
79
use objc2::{extern_protocol, ProtocolType};
810

911
fn sample_array(len: usize) -> Id<NSArray<NSObject>> {
@@ -283,3 +285,15 @@ fn test_trait_retainable() {
283285
let _ = NSArray::from_id_slice(&[obj.clone(), obj.clone()]);
284286
let _ = NSArray::from_vec(vec![obj.clone(), obj.clone()]);
285287
}
288+
289+
#[test]
290+
fn test_access_anyobject() {
291+
let obj: Id<AnyObject> = Id::into_super(NSObject::new());
292+
let array = NSArray::from_id_slice(&[obj.clone(), obj.clone()]);
293+
assert!(ptr::eq(&array[0], &*obj));
294+
assert!(ptr::eq(array.get(0).unwrap(), &*obj));
295+
assert!(ptr::eq(&*array.get_retained(0).unwrap(), &*obj));
296+
for _ in array.iter() {}
297+
for _ in array.iter_retained() {}
298+
for _ in array {}
299+
}

crates/objc2/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5656

5757
### Fixed
5858
* Fixed the name of the protocol that `NSObjectProtocol` references.
59+
* Allow cloning `Id<AnyObject>`.
5960

6061
### Removed
6162
* **BREAKING**: Removed `ProtocolType` implementation for `NSObject`.

crates/objc2/src/mutability.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
//! bug.
3333
use core::marker::PhantomData;
3434

35-
use crate::runtime::ProtocolObject;
35+
use crate::runtime::{AnyObject, ProtocolObject};
3636
use crate::{ClassType, Message, ProtocolType};
3737

3838
mod private_mutability {
@@ -266,6 +266,7 @@ mod private_traits {
266266

267267
impl<T: ?Sized + ClassType> private_traits::Sealed for T {}
268268
impl<P: ?Sized + ProtocolType> private_traits::Sealed for ProtocolObject<P> {}
269+
impl private_traits::Sealed for AnyObject {}
269270

270271
/// Marker trait for classes where [`Id::clone`] is safe.
271272
///
@@ -299,6 +300,8 @@ impl MutabilityIsIdCloneable for MainThreadOnly {}
299300

300301
unsafe impl<T: ?Sized + ClassType> IsIdCloneable for T where T::Mutability: MutabilityIsIdCloneable {}
301302
unsafe impl<P: ?Sized + ProtocolType + IsIdCloneable> IsIdCloneable for ProtocolObject<P> {}
303+
// SAFETY: Same as for root classes.
304+
unsafe impl IsIdCloneable for AnyObject {}
302305

303306
/// Marker trait for classes where the `retain` selector is always safe.
304307
///

crates/objc2/src/rc/id.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,9 +951,21 @@ mod tests {
951951
assert_retain_count(&cloned, 2);
952952
assert_retain_count(&obj, 2);
953953

954+
let obj = Id::into_super(Id::into_super(obj));
955+
let cloned_and_type_erased = obj.clone();
956+
expected.retain += 1;
957+
expected.assert_current();
958+
assert_retain_count(&cloned_and_type_erased, 3);
959+
assert_retain_count(&obj, 3);
960+
954961
drop(obj);
955962
expected.release += 1;
956963
expected.assert_current();
964+
assert_retain_count(&cloned, 2);
965+
966+
drop(cloned_and_type_erased);
967+
expected.release += 1;
968+
expected.assert_current();
957969
assert_retain_count(&cloned, 1);
958970

959971
drop(cloned);

0 commit comments

Comments
 (0)