Skip to content

Commit 759b9e1

Browse files
committed
Remove INSObject::Ownership
Instead, it is present on the types that actually need it. This is in preparation for bigger changes to objc2-foundation, see #58.
1 parent e4f5c60 commit 759b9e1

File tree

11 files changed

+89
-59
lines changed

11 files changed

+89
-59
lines changed

objc2-foundation/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## Unreleased - YYYY-MM-DD
88

9+
### Added
10+
* **BREAKING**: Added associated `Ownership` type to `NSCopying`.
11+
* **BREAKING**: Added associated `Ownership` type to `INSData`.
12+
* **BREAKING**: Added associated `Ownership` type to `INSArray`.
13+
14+
### Changed
15+
* **BREAKING**: Made some creation methods a bit less generic (e.g.
16+
`INSDictionary::from_keys_and_objects` now always returns `Id<_, Shared>`).
17+
18+
### Removed
19+
* **BREAKING**: Removed associated `Ownership` type from `INSObject`; instead,
20+
it is present on the types that actually need it (for example `NSCopying`).
21+
922
## 0.2.0-alpha.2 - 2021-11-22
1023

1124
### Added

objc2-foundation/examples/class_with_lifetime.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ impl<'a> MyObject<'a> {
5353
static MYOBJECT_REGISTER_CLASS: Once = Once::new();
5454

5555
unsafe impl INSObject for MyObject<'_> {
56-
type Ownership = Owned;
57-
5856
fn class() -> &'static Class {
5957
MYOBJECT_REGISTER_CLASS.call_once(|| {
6058
let superclass = NSObject::class();

objc2-foundation/examples/custom_class.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ unsafe impl RefEncode for MYObject {
2323
}
2424

2525
impl MYObject {
26-
fn new() -> Id<Self, <Self as INSObject>::Ownership> {
26+
fn new() -> Id<Self, Owned> {
2727
let cls = Self::class();
2828
unsafe { Id::new(NonNull::new_unchecked(msg_send![cls, new])) }
2929
}
@@ -48,8 +48,6 @@ unsafe impl Message for MYObject {}
4848
static MYOBJECT_REGISTER_CLASS: Once = Once::new();
4949

5050
unsafe impl INSObject for MYObject {
51-
type Ownership = Owned;
52-
5351
fn class() -> &'static Class {
5452
MYOBJECT_REGISTER_CLASS.call_once(|| {
5553
let superclass = NSObject::class();

objc2-foundation/src/array.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ unsafe fn from_refs<A: INSArray>(refs: &[&A::Item]) -> Id<A, A::Ownership> {
2929
}
3030

3131
pub unsafe trait INSArray: INSObject {
32+
type Ownership: Ownership;
3233
type Item: INSObject;
3334
type ItemOwnership: Ownership;
3435

35-
unsafe_def_fn!(fn new);
36+
unsafe_def_fn!(fn new -> Self::Ownership);
3637

3738
#[doc(alias = "count")]
3839
fn len(&self) -> usize {
@@ -165,33 +166,36 @@ pub unsafe trait INSArray: INSObject {
165166
///
166167
/// `Id<NSArray<T, Owned>, Shared>` is possible, but pretty useless.
167168
/// TODO: Can we make it impossible? Should we?
169+
///
170+
/// What about `Id<NSArray<T, Shared>, Owned>`?
168171
pub struct NSArray<T, O: Ownership> {
169172
item: PhantomData<Id<T, O>>,
170173
}
171174

172175
object_impl!(unsafe NSArray<T, O: Ownership>);
173176

174177
unsafe impl<T: INSObject, O: Ownership> INSObject for NSArray<T, O> {
178+
fn class() -> &'static Class {
179+
class!(NSArray)
180+
}
181+
}
182+
183+
unsafe impl<T: INSObject, O: Ownership> INSArray for NSArray<T, O> {
175184
/// The `NSArray` itself (length and number of items) is always immutable,
176185
/// but we would like to know when we're the only owner of the array, to
177186
/// allow mutation of the array's items.
178187
///
179188
/// We only implement `INSCopying` when `O = Shared`, so this is safe.
180189
type Ownership = O;
181190

182-
fn class() -> &'static Class {
183-
class!(NSArray)
184-
}
185-
}
186-
187-
unsafe impl<T: INSObject, O: Ownership> INSArray for NSArray<T, O> {
188191
type Item = T;
189192
type ItemOwnership = O;
190193
}
191194

192195
// Copying only possible when ItemOwnership = Shared
193196

194197
unsafe impl<T: INSObject> INSCopying for NSArray<T, Shared> {
198+
type Ownership = Shared;
195199
type Output = NSArray<T, Shared>;
196200
}
197201

@@ -322,14 +326,13 @@ pub struct NSMutableArray<T, O: Ownership> {
322326
object_impl!(unsafe NSMutableArray<T, O: Ownership>);
323327

324328
unsafe impl<T: INSObject, O: Ownership> INSObject for NSMutableArray<T, O> {
325-
type Ownership = Owned;
326-
327329
fn class() -> &'static Class {
328330
class!(NSMutableArray)
329331
}
330332
}
331333

332334
unsafe impl<T: INSObject, O: Ownership> INSArray for NSMutableArray<T, O> {
335+
type Ownership = Owned;
333336
type Item = T;
334337
type ItemOwnership = O;
335338
}
@@ -339,6 +342,7 @@ unsafe impl<T: INSObject, O: Ownership> INSMutableArray for NSMutableArray<T, O>
339342
// Copying only possible when ItemOwnership = Shared
340343

341344
unsafe impl<T: INSObject> INSCopying for NSMutableArray<T, Shared> {
345+
type Ownership = Shared;
342346
type Output = NSArray<T, Shared>;
343347
}
344348

objc2-foundation/src/copying.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,53 @@
11
use core::ptr::NonNull;
22

33
use objc2::msg_send;
4-
use objc2::rc::{Id, Owned};
4+
use objc2::rc::{Id, Owned, Ownership};
55

66
use super::INSObject;
77

88
pub unsafe trait INSCopying: INSObject {
9-
/// This can be an [`Owned`] [`INSObject`] if and only if `copy` creates a
10-
/// new instance, see the following example:
9+
/// Indicates whether the type is mutable or immutable.
10+
///
11+
/// This can be [`Owned`] if and only if `copy` creates a new instance,
12+
/// see the following example:
1113
///
1214
/// ```ignore
13-
/// let x: Id<MyObject, Owned> = MyObject::new();
15+
/// let x: Id<MyObject, _> = MyObject::new();
1416
/// // This is valid only if `y` is a new instance. Otherwise `x` and `y`
1517
/// // would be able to create aliasing mutable references!
1618
/// let y: Id<MyObject, Owned> = x.copy();
1719
/// ```
20+
///
21+
/// Note that for the same reason, you should be careful when defining
22+
/// `new` methods on your object; e.g. immutable types like [`NSString`]
23+
/// don't return `Id<NSString, Owned>`, because that would allow this
24+
/// trait to create an aliasing `Id<NSString, Shared>` (since sending the
25+
/// `copy` message (and others) does not create a new instance, but
26+
/// instead just retains the instance).
27+
///
28+
/// [`NSString`]: crate::NSString
29+
type Ownership: Ownership;
30+
31+
/// The output type.
32+
///
33+
/// This is usually `Self`, but e.g. `NSMutableString` returns `NSString`.
34+
/// TODO: Verify???
1835
type Output: INSObject;
1936

20-
fn copy(&self) -> Id<Self::Output, <Self::Output as INSObject>::Ownership> {
37+
fn copy(&self) -> Id<Self::Output, Self::Ownership> {
2138
unsafe {
2239
let obj: *mut Self::Output = msg_send![self, copy];
2340
Id::new(NonNull::new_unchecked(obj))
2441
}
2542
}
2643
}
2744

45+
/// TODO
46+
///
47+
/// Note that the `mutableCopy` selector must return an owned object!
2848
pub unsafe trait INSMutableCopying: INSObject {
29-
/// An [`Owned`] [`INSObject`] is required to be able to return an owned
30-
/// [`Id`].
31-
type Output: INSObject<Ownership = Owned>;
49+
/// TODO
50+
type Output: INSObject;
3251

3352
fn mutable_copy(&self) -> Id<Self::Output, Owned> {
3453
unsafe {

objc2-foundation/src/data.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ use core::{ffi::c_void, ptr::NonNull};
66

77
use super::{INSCopying, INSMutableCopying, INSObject, NSRange};
88
use objc2::msg_send;
9-
use objc2::rc::{Id, Owned, Shared};
9+
use objc2::rc::{Id, Owned, Ownership, Shared};
1010

1111
pub unsafe trait INSData: INSObject {
12-
unsafe_def_fn!(fn new);
12+
type Ownership: Ownership;
13+
14+
unsafe_def_fn!(fn new -> Self::Ownership);
1315

1416
fn len(&self) -> usize {
1517
unsafe { msg_send![self, length] }
@@ -90,11 +92,14 @@ pub unsafe trait INSData: INSObject {
9092
}
9193
}
9294

93-
object_struct!(unsafe NSData, Shared);
95+
object_struct!(unsafe NSData);
9496

95-
unsafe impl INSData for NSData {}
97+
unsafe impl INSData for NSData {
98+
type Ownership = Shared;
99+
}
96100

97101
unsafe impl INSCopying for NSData {
102+
type Ownership = Shared;
98103
type Output = NSData;
99104
}
100105

@@ -150,13 +155,16 @@ pub unsafe trait INSMutableData: INSData {
150155
}
151156
}
152157

153-
object_struct!(unsafe NSMutableData, Owned);
158+
object_struct!(unsafe NSMutableData);
154159

155-
unsafe impl INSData for NSMutableData {}
160+
unsafe impl INSData for NSMutableData {
161+
type Ownership = Owned;
162+
}
156163

157164
unsafe impl INSMutableData for NSMutableData {}
158165

159166
unsafe impl INSCopying for NSMutableData {
167+
type Ownership = Shared;
160168
type Output = NSData;
161169
}
162170

objc2-foundation/src/dictionary.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use objc2::{class, msg_send};
1010

1111
use super::{INSCopying, INSFastEnumeration, INSObject, NSArray, NSEnumerator};
1212

13-
unsafe fn from_refs<D, T>(keys: &[&T], vals: &[&D::Value]) -> Id<D, D::Ownership>
13+
unsafe fn from_refs<D, T>(keys: &[&T], vals: &[&D::Value]) -> Id<D, Shared>
1414
where
1515
D: INSDictionary,
1616
T: INSCopying<Output = D::Key>,
@@ -35,8 +35,6 @@ pub unsafe trait INSDictionary: INSObject {
3535
type Value: INSObject;
3636
type ValueOwnership: Ownership;
3737

38-
unsafe_def_fn!(fn new);
39-
4038
#[doc(alias = "count")]
4139
fn len(&self) -> usize {
4240
unsafe { msg_send![self, count] }
@@ -124,7 +122,7 @@ pub unsafe trait INSDictionary: INSObject {
124122
fn from_keys_and_objects<T>(
125123
keys: &[&T],
126124
vals: Vec<Id<Self::Value, Self::ValueOwnership>>,
127-
) -> Id<Self, Self::Ownership>
125+
) -> Id<Self, Shared>
128126
where
129127
T: INSCopying<Output = Self::Key>,
130128
{
@@ -148,9 +146,11 @@ pub struct NSDictionary<K, V> {
148146

149147
object_impl!(unsafe NSDictionary<K, V>);
150148

151-
unsafe impl<K: INSObject, V: INSObject> INSObject for NSDictionary<K, V> {
152-
type Ownership = Shared;
149+
impl<K: INSObject, V: INSObject> NSDictionary<K, V> {
150+
unsafe_def_fn!(pub fn new -> Shared);
151+
}
153152

153+
unsafe impl<K: INSObject, V: INSObject> INSObject for NSDictionary<K, V> {
154154
fn class() -> &'static Class {
155155
class!(NSDictionary)
156156
}

objc2-foundation/src/macros.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/// example: `NSAutoreleasePool` does not have this). Finally the ownership
88
/// must be correct for this class.
99
macro_rules! object_struct {
10-
(unsafe $name:ident, $ownership:ty) => {
10+
(unsafe $name:ident) => {
1111
// TODO: `extern type`
1212
#[repr(C)]
1313
pub struct $name {
@@ -21,8 +21,6 @@ macro_rules! object_struct {
2121
}
2222

2323
unsafe impl $crate::INSObject for $name {
24-
type Ownership = $ownership;
25-
2624
fn class() -> &'static ::objc2::runtime::Class {
2725
::objc2::class!($name)
2826
}
@@ -77,8 +75,8 @@ macro_rules! object_impl {
7775
}
7876

7977
macro_rules! unsafe_def_fn {
80-
($v:vis fn new) => {
81-
$v fn new() -> Id<Self, <Self as INSObject>::Ownership> {
78+
($v:vis fn new -> $o:ty) => {
79+
$v fn new() -> Id<Self, $o> {
8280
let cls = <Self as INSObject>::class();
8381
unsafe { Id::new(NonNull::new_unchecked(msg_send![cls, new])) }
8482
}

objc2-foundation/src/object.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::ptr::NonNull;
22

33
use objc2::msg_send;
4-
use objc2::rc::{Id, Owned, Ownership, Shared};
4+
use objc2::rc::{Id, Owned, Shared};
55
use objc2::runtime::{Bool, Class};
66
use objc2::Message;
77

@@ -12,16 +12,6 @@ use super::NSString;
1212
// type pointer to an Object pointer, because dynamically-sized types can have
1313
// fat pointers (two words) instead of real pointers.
1414
pub unsafe trait INSObject: Sized + Message {
15-
/// Indicates whether the type is mutable or immutable.
16-
///
17-
/// [`Shared`] means that only a shared [`Id`] can ever be held to this
18-
/// object. This is important for immutable types like `NSString`, because
19-
/// sending the `copy` message (and others) does not create a new
20-
/// instance, but instead just retains the instance.
21-
///
22-
/// Most objects are mutable and hence can return [`Owned`] [`Id`]s.
23-
type Ownership: Ownership;
24-
2515
fn class() -> &'static Class;
2616

2717
fn hash_code(&self) -> usize {
@@ -47,10 +37,10 @@ pub unsafe trait INSObject: Sized + Message {
4737
}
4838
}
4939

50-
object_struct!(unsafe NSObject, Owned);
40+
object_struct!(unsafe NSObject);
5141

5242
impl NSObject {
53-
unsafe_def_fn!(pub fn new);
43+
unsafe_def_fn!(pub fn new -> Owned);
5444
}
5545

5646
#[cfg(test)]

objc2-foundation/src/string.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ const UTF8_ENCODING: i32 = 4;
2222
const NSNotFound: ffi::NSInteger = ffi::NSIntegerMax;
2323

2424
pub unsafe trait INSString: INSObject {
25-
unsafe_def_fn!(fn new);
26-
2725
fn len(&self) -> usize {
2826
unsafe { msg_send![self, lengthOfBytesUsingEncoding: UTF8_ENCODING] }
2927
}
@@ -86,7 +84,7 @@ pub unsafe trait INSString: INSObject {
8684
str::from_utf8(bytes).unwrap()
8785
}
8886

89-
fn from_str(string: &str) -> Id<Self, Self::Ownership> {
87+
fn from_str(string: &str) -> Id<Self, Shared> {
9088
let cls = Self::class();
9189
let bytes = string.as_ptr() as *const c_void;
9290
unsafe {
@@ -102,11 +100,16 @@ pub unsafe trait INSString: INSObject {
102100
}
103101
}
104102

105-
object_struct!(unsafe NSString, Shared);
103+
object_struct!(unsafe NSString);
104+
105+
impl NSString {
106+
unsafe_def_fn!(pub fn new -> Shared);
107+
}
106108

107109
unsafe impl INSString for NSString {}
108110

109111
unsafe impl INSCopying for NSString {
112+
type Ownership = Shared;
110113
type Output = NSString;
111114
}
112115

0 commit comments

Comments
 (0)