Skip to content

Commit c6f851c

Browse files
committed
Implement mutability marker traits for ProtocolObject as well
1 parent 83b4a73 commit c6f851c

21 files changed

+273
-94
lines changed

crates/icrate/src/additions/Foundation/array.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -391,15 +391,15 @@ __impl_iter! {
391391
pub struct IterMut<'a, T: Message>(iter::IterMut<'a, NSArray<T>>);
392392

393393
__impl_iter! {
394-
impl<'a, T: IsMutable> Iterator<Item = &'a mut T> for IterMut<'a, T> { ... }
394+
impl<'a, T: Message + IsMutable> Iterator<Item = &'a mut T> for IterMut<'a, T> { ... }
395395
}
396396

397397
/// An iterator that retains the items of a `NSArray`.
398398
#[derive(Debug)]
399399
pub struct IterRetained<'a, T: Message>(iter::IterRetained<'a, NSArray<T>>);
400400

401401
__impl_iter! {
402-
impl<'a, T: IsIdCloneable> Iterator<Item = Id<T>> for IterRetained<'a, T> { ... }
402+
impl<'a, T: Message + IsIdCloneable> Iterator<Item = Id<T>> for IterRetained<'a, T> { ... }
403403
}
404404

405405
/// A consuming iterator over the items of a `NSArray`.
@@ -420,16 +420,16 @@ __impl_into_iter! {
420420
type IntoIter = Iter<'_, T>;
421421
}
422422

423-
impl<T: IsMutable> IntoIterator for &mut NSArray<T> {
423+
impl<T: Message + IsMutable> IntoIterator for &mut NSArray<T> {
424424
type IntoIter = IterMut<'_, T>;
425425
}
426426

427427
#[cfg(feature = "Foundation_NSMutableArray")]
428-
impl<T: IsMutable> IntoIterator for &mut NSMutableArray<T> {
428+
impl<T: Message + IsMutable> IntoIterator for &mut NSMutableArray<T> {
429429
type IntoIter = IterMut<'_, T>;
430430
}
431431

432-
impl<T: IsIdCloneable> IntoIterator for Id<NSArray<T>> {
432+
impl<T: Message + IsIdCloneable> IntoIterator for Id<NSArray<T>> {
433433
type IntoIter = IntoIter<T>;
434434
}
435435

@@ -456,14 +456,14 @@ impl<T: Message> Index<usize> for NSMutableArray<T> {
456456
}
457457
}
458458

459-
impl<T: IsMutable> IndexMut<usize> for NSArray<T> {
459+
impl<T: Message + IsMutable> IndexMut<usize> for NSArray<T> {
460460
fn index_mut(&mut self, index: usize) -> &mut T {
461461
self.get_mut(index).unwrap()
462462
}
463463
}
464464

465465
#[cfg(feature = "Foundation_NSMutableArray")]
466-
impl<T: IsMutable> IndexMut<usize> for NSMutableArray<T> {
466+
impl<T: Message + IsMutable> IndexMut<usize> for NSMutableArray<T> {
467467
fn index_mut(&mut self, index: usize) -> &mut T {
468468
self.get_mut(index).unwrap()
469469
}
@@ -484,7 +484,7 @@ impl<T: Message> Extend<Id<T>> for NSMutableArray<T> {
484484
}
485485

486486
#[cfg(feature = "Foundation_NSMutableArray")]
487-
impl<'a, T: IsRetainable> Extend<&'a T> for NSMutableArray<T> {
487+
impl<'a, T: Message + IsRetainable> Extend<&'a T> for NSMutableArray<T> {
488488
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
489489
// SAFETY: Because of the `T: IsRetainable` bound, it is safe for the
490490
// array to retain the object here.
@@ -493,7 +493,7 @@ impl<'a, T: IsRetainable> Extend<&'a T> for NSMutableArray<T> {
493493
}
494494
}
495495

496-
impl<'a, T: IsRetainable + 'a> IdFromIterator<&'a T> for NSArray<T> {
496+
impl<'a, T: Message + IsRetainable + 'a> IdFromIterator<&'a T> for NSArray<T> {
497497
fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {
498498
let vec = Vec::from_iter(iter);
499499
Self::from_slice(&vec)
@@ -508,7 +508,7 @@ impl<T: Message> IdFromIterator<Id<T>> for NSArray<T> {
508508
}
509509

510510
#[cfg(feature = "Foundation_NSMutableArray")]
511-
impl<'a, T: IsRetainable + 'a> IdFromIterator<&'a T> for NSMutableArray<T> {
511+
impl<'a, T: Message + IsRetainable + 'a> IdFromIterator<&'a T> for NSMutableArray<T> {
512512
fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {
513513
let vec = Vec::from_iter(iter);
514514
Self::from_slice(&vec)

crates/icrate/src/additions/Foundation/dictionary.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ mod iter_helpers {
516516
);
517517

518518
__impl_iter! {
519-
impl<'a, K: IsIdCloneable, V: Message> Iterator<Item = Id<K>> for KeysRetained<'a, K, V> { ... }
519+
impl<'a, K: Message + IsIdCloneable, V: Message> Iterator<Item = Id<K>> for KeysRetained<'a, K, V> { ... }
520520
}
521521

522522
/// An iterator over the values of a `NSDictionary`.
@@ -536,7 +536,7 @@ mod iter_helpers {
536536
);
537537

538538
__impl_iter! {
539-
impl<'a, K: Message, V: IsMutable> Iterator<Item = &'a mut V> for ValuesMut<'a, K, V> { ... }
539+
impl<'a, K: Message, V: Message + IsMutable> Iterator<Item = &'a mut V> for ValuesMut<'a, K, V> { ... }
540540
}
541541

542542
/// A iterator that retains the values of a `NSDictionary`.
@@ -546,7 +546,7 @@ mod iter_helpers {
546546
);
547547

548548
__impl_iter! {
549-
impl<'a, K: Message, V: IsIdCloneable> Iterator<Item = Id<V>> for ValuesRetained<'a, K, V> { ... }
549+
impl<'a, K: Message, V: Message + IsIdCloneable> Iterator<Item = Id<V>> for ValuesRetained<'a, K, V> { ... }
550550
}
551551

552552
/// A consuming iterator over the values of a `NSDictionary`.
@@ -580,14 +580,16 @@ impl<'a, K: Message + Eq + Hash, V: Message> Index<&'a K> for NSMutableDictionar
580580
}
581581
}
582582

583-
impl<'a, K: Message + Eq + Hash, V: IsMutable> IndexMut<&'a K> for NSDictionary<K, V> {
583+
impl<'a, K: Message + Eq + Hash, V: Message + IsMutable> IndexMut<&'a K> for NSDictionary<K, V> {
584584
fn index_mut<'s>(&'s mut self, index: &'a K) -> &'s mut V {
585585
self.get_mut(index).unwrap()
586586
}
587587
}
588588

589589
#[cfg(feature = "Foundation_NSMutableDictionary")]
590-
impl<'a, K: Message + Eq + Hash, V: IsMutable> IndexMut<&'a K> for NSMutableDictionary<K, V> {
590+
impl<'a, K: Message + Eq + Hash, V: Message + IsMutable> IndexMut<&'a K>
591+
for NSMutableDictionary<K, V>
592+
{
591593
fn index_mut<'s>(&'s mut self, index: &'a K) -> &'s mut V {
592594
self.get_mut(index).unwrap()
593595
}

crates/icrate/src/additions/Foundation/enumerator.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Utilities for the `NSEnumerator` class.
22
#![cfg(feature = "Foundation_NSEnumerator")]
3-
use objc2::mutability::{IsIdCloneable, IsMutable};
4-
53
use super::iter;
64
use crate::common::*;
75
use crate::Foundation::NSEnumerator;

crates/icrate/src/additions/Foundation/iter.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ impl<C: FastEnumerationHelper> IntoIter<C> {
428428
}
429429
}
430430

431-
pub(crate) fn new_mutable<T: IsMutable + ClassType<Super = C>>(collection: Id<T>) -> Self
431+
pub(crate) fn new_mutable<T: ClassType<Super = C> + IsMutable>(collection: Id<T>) -> Self
432432
where
433433
C: IsIdCloneable,
434434
{
@@ -648,7 +648,7 @@ where
648648
}
649649
}
650650

651-
pub(crate) unsafe fn new_mutable<T: IsMutable + ClassType<Super = C>>(
651+
pub(crate) unsafe fn new_mutable<T: ClassType<Super = C> + IsMutable>(
652652
collection: Id<T>,
653653
enumerator: Id<E>,
654654
) -> Self
@@ -696,9 +696,9 @@ where
696696
#[doc(hidden)]
697697
macro_rules! __impl_iter {
698698
(
699-
impl<$($lifetime:lifetime, )? $t1:ident: $bound1:ident $(, $t2:ident: $bound2:ident)?> Iterator<Item = $item:ty> for $for:ty { ... }
699+
impl<$($lifetime:lifetime, )? $t1:ident: $bound1:ident $(+ $bound1_b:ident)? $(, $t2:ident: $bound2:ident $(+ $bound2_b:ident)?)?> Iterator<Item = $item:ty> for $for:ty { ... }
700700
) => {
701-
impl<$($lifetime, )? $t1: $bound1 $(, $t2: $bound2)?> Iterator for $for {
701+
impl<$($lifetime, )? $t1: $bound1 $(+ $bound1_b)? $(, $t2: $bound2 $(+ $bound2_b)?)?> Iterator for $for {
702702
type Item = $item;
703703

704704
#[inline]
@@ -743,14 +743,14 @@ macro_rules! __impl_into_iter {
743743
};
744744
(
745745
$(#[$m:meta])*
746-
impl<T: IsMutable> IntoIterator for &mut $ty:ident<T> {
746+
impl<T: Message + IsMutable> IntoIterator for &mut $ty:ident<T> {
747747
type IntoIter = $iter_mut:ident<'_, T>;
748748
}
749749

750750
$($rest:tt)*
751751
) => {
752752
$(#[$m])*
753-
impl<'a, T: IsMutable> IntoIterator for &'a mut $ty<T> {
753+
impl<'a, T: Message + IsMutable> IntoIterator for &'a mut $ty<T> {
754754
type Item = &'a mut T;
755755
type IntoIter = $iter_mut<'a, T>;
756756

@@ -766,14 +766,14 @@ macro_rules! __impl_into_iter {
766766
};
767767
(
768768
$(#[$m:meta])*
769-
impl<T: IsIdCloneable> IntoIterator for Id<$ty:ident<T>> {
769+
impl<T: Message + IsIdCloneable> IntoIterator for Id<$ty:ident<T>> {
770770
type IntoIter = $into_iter:ident<T>;
771771
}
772772

773773
$($rest:tt)*
774774
) => {
775775
$(#[$m])*
776-
impl<T: IsIdCloneable> objc2::rc::IdIntoIterator for $ty<T> {
776+
impl<T: Message + IsIdCloneable> objc2::rc::IdIntoIterator for $ty<T> {
777777
type Item = Id<T>;
778778
type IntoIter = $into_iter<T>;
779779

crates/icrate/src/additions/Foundation/set.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ __impl_iter! {
501501
pub struct IterRetained<'a, T: Message>(iter::IterRetained<'a, NSSet<T>>);
502502

503503
__impl_iter! {
504-
impl<'a, T: IsIdCloneable> Iterator<Item = Id<T>> for IterRetained<'a, T> { ... }
504+
impl<'a, T: Message + IsIdCloneable> Iterator<Item = Id<T>> for IterRetained<'a, T> { ... }
505505
}
506506

507507
/// A consuming iterator over the items of a `NSSet`.
@@ -522,7 +522,7 @@ __impl_into_iter! {
522522
type IntoIter = Iter<'_, T>;
523523
}
524524

525-
impl<T: IsIdCloneable> IntoIterator for Id<NSSet<T>> {
525+
impl<T: Message + IsIdCloneable> IntoIterator for Id<NSSet<T>> {
526526
type IntoIter = IntoIter<T>;
527527
}
528528

@@ -549,15 +549,17 @@ impl<T: Message + Eq + Hash + HasStableHash> Extend<Id<T>> for NSMutableSet<T> {
549549
}
550550

551551
#[cfg(feature = "Foundation_NSMutableSet")]
552-
impl<'a, T: IsRetainable + Eq + Hash + HasStableHash> Extend<&'a T> for NSMutableSet<T> {
552+
impl<'a, T: Message + Eq + Hash + HasStableHash + IsRetainable> Extend<&'a T> for NSMutableSet<T> {
553553
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
554554
iter.into_iter().for_each(move |item| {
555555
self.insert(item);
556556
})
557557
}
558558
}
559559

560-
impl<'a, T: IsRetainable + Eq + Hash + HasStableHash + 'a> IdFromIterator<&'a T> for NSSet<T> {
560+
impl<'a, T: Message + Eq + Hash + HasStableHash + IsRetainable + 'a> IdFromIterator<&'a T>
561+
for NSSet<T>
562+
{
561563
fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {
562564
let vec = Vec::from_iter(iter);
563565
Self::from_slice(&vec)
@@ -572,7 +574,7 @@ impl<T: Message + Eq + Hash + HasStableHash> IdFromIterator<Id<T>> for NSSet<T>
572574
}
573575

574576
#[cfg(feature = "Foundation_NSMutableSet")]
575-
impl<'a, T: IsRetainable + Eq + Hash + HasStableHash + 'a> IdFromIterator<&'a T>
577+
impl<'a, T: Message + Eq + Hash + HasStableHash + IsRetainable + 'a> IdFromIterator<&'a T>
576578
for NSMutableSet<T>
577579
{
578580
fn id_from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Id<Self> {

crates/icrate/src/additions/Foundation/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub(crate) fn id_ptr_cast_const<T: ?Sized>(objects: *const Id<T>) -> *mut NonNul
6868
#[inline]
6969
pub(crate) unsafe fn collection_retain_id<T>(obj: &T) -> Id<T>
7070
where
71-
T: IsIdCloneable,
71+
T: Message + IsIdCloneable,
7272
{
7373
// SAFETY: We're allowed to access `&Id<T>` from `&self` in collections,
7474
// and since `T: IsIdCloneable`, we can convert that to `Id<T>`.

crates/icrate/src/fixes/Foundation/copy.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ use crate::common::*;
44
use crate::Foundation::{self, NSCopying, NSMutableCopying};
55

66
#[cfg(feature = "Foundation_NSArray")]
7-
impl<T: IsIdCloneable> ToOwned for Foundation::NSArray<T> {
7+
impl<T: Message + IsIdCloneable> ToOwned for Foundation::NSArray<T> {
88
type Owned = Id<Self>;
99
fn to_owned(&self) -> Self::Owned {
1010
self.copy()
1111
}
1212
}
1313

1414
#[cfg(feature = "Foundation_NSMutableArray")]
15-
impl<T: IsIdCloneable> ToOwned for Foundation::NSMutableArray<T> {
15+
impl<T: Message + IsIdCloneable> ToOwned for Foundation::NSMutableArray<T> {
1616
type Owned = Id<Self>;
1717
fn to_owned(&self) -> Self::Owned {
1818
self.mutableCopy()
@@ -44,15 +44,15 @@ impl ToOwned for Foundation::NSException {
4444
}
4545

4646
#[cfg(feature = "Foundation_NSSet")]
47-
impl<T: IsIdCloneable> ToOwned for Foundation::NSSet<T> {
47+
impl<T: Message + IsIdCloneable> ToOwned for Foundation::NSSet<T> {
4848
type Owned = Id<Self>;
4949
fn to_owned(&self) -> Self::Owned {
5050
self.copy()
5151
}
5252
}
5353

5454
#[cfg(feature = "Foundation_NSMutableSet")]
55-
impl<T: IsIdCloneable> ToOwned for Foundation::NSMutableSet<T> {
55+
impl<T: Message + IsIdCloneable> ToOwned for Foundation::NSMutableSet<T> {
5656
type Owned = Id<Self>;
5757
fn to_owned(&self) -> Self::Owned {
5858
self.mutableCopy()

crates/icrate/tests/array.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#![cfg(feature = "Foundation_NSArray")]
22
#![cfg(feature = "Foundation_NSNumber")]
33
use icrate::Foundation::{NSArray, NSNumber, NSObject};
4-
use objc2::rc::Id;
5-
use objc2::rc::{__RcTestObject, __ThreadTestData};
4+
use objc2::mutability::IsRetainable;
5+
use objc2::rc::{Id, __RcTestObject, __ThreadTestData};
6+
use objc2::runtime::ProtocolObject;
7+
use objc2::{extern_protocol, ProtocolType};
68

79
fn sample_array(len: usize) -> Id<NSArray<NSObject>> {
810
let mut vec = Vec::with_capacity(len);
@@ -262,3 +264,22 @@ fn test_generic_ownership_traits() {
262264

263265
assert_partialeq::<NSArray<NSObject>>();
264266
}
267+
268+
#[test]
269+
fn test_trait_retainable() {
270+
extern_protocol!(
271+
#[allow(clippy::missing_safety_doc)]
272+
unsafe trait TestProtocol: IsRetainable {}
273+
274+
unsafe impl ProtocolType for dyn TestProtocol {
275+
const NAME: &'static str = "NSObject";
276+
}
277+
);
278+
279+
unsafe impl TestProtocol for NSNumber {}
280+
281+
let obj: Id<ProtocolObject<dyn TestProtocol>> = ProtocolObject::from_id(NSNumber::new_i32(42));
282+
let _ = NSArray::from_slice(&[&*obj, &*obj]);
283+
let _ = NSArray::from_id_slice(&[obj.clone(), obj.clone()]);
284+
let _ = NSArray::from_vec(vec![obj.clone(), obj.clone()]);
285+
}

crates/icrate/tests/copying.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![cfg(feature = "Foundation")]
2+
#![cfg(feature = "Foundation_NSString")]
3+
use icrate::Foundation::{NSCopying, NSMutableCopying, NSString};
4+
use objc2::{rc::Id, runtime::ProtocolObject};
5+
6+
#[test]
7+
fn copy() {
8+
let obj = NSString::new();
9+
let protocol_object: &ProtocolObject<dyn NSCopying> = ProtocolObject::from_ref(&*obj);
10+
let _: Id<ProtocolObject<dyn NSCopying>> = protocol_object.copy();
11+
}
12+
13+
#[test]
14+
fn copy_mutable() {
15+
let obj = NSString::new();
16+
let protocol_object: &ProtocolObject<dyn NSMutableCopying> = ProtocolObject::from_ref(&*obj);
17+
let _: Id<ProtocolObject<dyn NSMutableCopying>> = protocol_object.mutableCopy();
18+
}

crates/objc2/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1818
### Changed
1919
* **BREAKING**: `AnyClass::verify_sel` now take more well-defined types
2020
`EncodeArguments` and `EncodeReturn`.
21+
* **BREAKING**: Changed how the `mutability` traits work; these no longer have
22+
`ClassType` as a super trait, allowing them to work for `ProtocolObject` as
23+
well.
24+
25+
This effectively means you can now `copy` a `ProtocolObject<dyn NSCopying>`.
26+
* **BREAKING**: Allow implementing `DefaultId` for any type, not just those
27+
who are `IsAllocableAnyThread`.
2128

2229
### Deprecated
2330
* Soft deprecated using `msg_send!` without a comma between arguments (i.e.

0 commit comments

Comments
 (0)