Skip to content

Commit 032809f

Browse files
authored
Merge pull request #419 from madsmtm/redo-ownership
Redo how ownership works
2 parents 72288fb + 01f08a7 commit 032809f

File tree

189 files changed

+4890
-3194
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+4890
-3194
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ jobs:
144144
key: cargo-${{ github.job }}-${{ matrix.name }}-${{ hashFiles('**/Cargo.lock') }}
145145

146146
- name: cargo doc
147+
# Disable cargo doc checking for now, `NSEnumerator2<'a, T>` is broken
148+
# on current nightly.
149+
if: false
147150
run: cargo doc --no-deps --document-private-items ${{ matrix.args }}
148151

149152
- name: cargo clippy

Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LAYERED_SAFETY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ correctly.
144144
The `NSData` example again.
145145

146146
```rust
147-
let obj: Id<NSObject, Shared> = unsafe { msg_send_id![class!(NSData), new] };
147+
let obj: Id<NSObject> = unsafe { msg_send_id![class!(NSData), new] };
148148
let length: NSUInteger = unsafe { msg_send![&obj, length] };
149149
// `obj` goes out of scope, `release` is automatically sent to the object
150150
```
@@ -181,13 +181,14 @@ extern_class!(
181181

182182
unsafe impl ClassType for NSData {
183183
type Super = NSObject;
184+
type Mutability = ImmutableWithMutableSubclass<NSMutableData>;
184185
}
185186
);
186187

187188
extern_methods!(
188189
unsafe impl NSData {
189190
#[method_id(new)]
190-
fn new() -> Id<Self, Shared>;
191+
fn new() -> Id<Self>;
191192

192193
#[method(length)]
193194
fn length(&self) -> NSUInteger;

crates/header-translator/src/cache.rs

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::file::File;
77
use crate::id::ItemIdentifier;
88
use crate::method::Method;
99
use crate::output::Output;
10-
use crate::rust_type::Ownership;
1110
use crate::stmt::Stmt;
1211

1312
#[derive(Debug, PartialEq, Clone)]
@@ -37,14 +36,12 @@ impl ClassCache {
3736
#[derive(Debug, PartialEq, Clone)]
3837
pub struct Cache<'a> {
3938
classes: BTreeMap<ItemIdentifier, ClassCache>,
40-
ownership_map: BTreeMap<String, Ownership>,
4139
config: &'a Config,
4240
}
4341

4442
impl<'a> Cache<'a> {
4543
pub fn new(output: &Output, config: &'a Config) -> Self {
4644
let mut classes: BTreeMap<_, ClassCache> = BTreeMap::new();
47-
let mut ownership_map: BTreeMap<_, Ownership> = BTreeMap::new();
4845

4946
for (name, library) in &output.libraries {
5047
let _span = debug_span!("library", name).entered();
@@ -55,20 +52,11 @@ impl<'a> Cache<'a> {
5552
let cache = classes.entry(cls.clone()).or_default();
5653
cache.to_emit.push(method_cache);
5754
}
58-
if let Stmt::ClassDecl { id, ownership, .. } = stmt {
59-
if *ownership != Ownership::default() {
60-
ownership_map.insert(id.name.clone(), ownership.clone());
61-
}
62-
}
6355
}
6456
}
6557
}
6658

67-
Self {
68-
classes,
69-
ownership_map,
70-
config,
71-
}
59+
Self { classes, config }
7260
}
7361

7462
fn cache_stmt(stmt: &Stmt) -> Option<(&ItemIdentifier, MethodCache)> {
@@ -159,6 +147,7 @@ impl<'a> Cache<'a> {
159147

160148
let mut new_stmts = Vec::new();
161149
for stmt in &mut file.stmts {
150+
#[allow(clippy::single_match)] // There will be others
162151
match stmt {
163152
Stmt::ClassDecl {
164153
id,
@@ -182,7 +171,7 @@ impl<'a> Cache<'a> {
182171
for (superclass, _) in &*superclasses {
183172
if let Some(cache) = self.classes.get(superclass) {
184173
new_stmts.extend(cache.to_emit.iter().filter_map(|cache| {
185-
let mut methods: Vec<_> = cache
174+
let methods: Vec<_> = cache
186175
.methods
187176
.iter()
188177
.filter(|method| !seen_methods.contains(&method.id()))
@@ -197,8 +186,6 @@ impl<'a> Cache<'a> {
197186
return None;
198187
}
199188

200-
self.update_methods(&mut methods, &id.name);
201-
202189
Some(Stmt::Methods {
203190
cls: id.clone(),
204191
generics: generics.clone(),
@@ -217,12 +204,6 @@ impl<'a> Cache<'a> {
217204
}
218205
}
219206
}
220-
Stmt::Methods { cls, methods, .. } => {
221-
self.update_methods(methods, &cls.name);
222-
}
223-
Stmt::ProtocolDecl { id, methods, .. } => {
224-
self.update_methods(methods, &id.name);
225-
}
226207
_ => {}
227208
}
228209
}
@@ -257,17 +238,4 @@ impl<'a> Cache<'a> {
257238
file.stmts.push(stmt);
258239
}
259240
}
260-
261-
fn update_methods(&self, methods: &mut [Method], self_means: &str) {
262-
for method in methods {
263-
// Beware! We make instance methods return `Owned` as well, though
264-
// those are basically never safe (since they'd refer to mutable
265-
// data without a lifetime tied to the primary owner).
266-
method.result_type.set_ownership(|name| {
267-
let name = if name == "Self" { self_means } else { name };
268-
269-
self.ownership_map.get(name).cloned().unwrap_or_default()
270-
});
271-
}
272-
}
273241
}

crates/header-translator/src/config.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use std::path::Path;
66
use serde::Deserialize;
77

88
use crate::data;
9-
use crate::rust_type::Ownership;
10-
use crate::stmt::Derives;
9+
use crate::stmt::{Derives, Mutability};
1110

1211
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
1312
#[serde(deny_unknown_fields)]
@@ -96,9 +95,8 @@ pub struct ClassData {
9695
pub categories: HashMap<String, CategoryData>,
9796
#[serde(default)]
9897
pub derives: Derives,
99-
#[serde(rename = "owned")]
100-
#[serde(default)]
101-
pub ownership: Ownership,
98+
#[serde(skip)]
99+
pub mutability: Mutability,
102100
#[serde(rename = "skipped-protocols")]
103101
#[serde(default)]
104102
pub skipped_protocols: HashSet<String>,
@@ -156,8 +154,7 @@ pub struct MethodData {
156154
pub unsafe_: bool,
157155
#[serde(default = "skipped_default")]
158156
pub skipped: bool,
159-
#[serde(default = "mutating_default")]
160-
pub mutating: bool,
157+
pub mutating: Option<bool>,
161158
}
162159

163160
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
@@ -191,16 +188,12 @@ fn skipped_default() -> bool {
191188
false
192189
}
193190

194-
fn mutating_default() -> bool {
195-
false
196-
}
197-
198191
impl Default for MethodData {
199192
fn default() -> Self {
200193
Self {
201194
unsafe_: unsafe_default(),
202195
skipped: skipped_default(),
203-
mutating: mutating_default(),
196+
mutating: None,
204197
}
205198
}
206199
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
data! {
2+
// Subclasses `NSMutableAttributedString`, though I think this should
3+
// actually be `InteriorMutable`?
4+
class NSTextStorage: Mutable {}
25
}

crates/header-translator/src/data/Foundation.rs

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
data! {
2-
class NSArray {
2+
// SAFETY: `new` or `initWithObjects:` may choose to deduplicate arrays,
3+
// and returning mutable references to those would be unsound - hence
4+
// `NSArray` cannot be mutable.
5+
class NSArray: ImmutableWithMutableSubclass<Foundation::NSMutableArray> {
36
unsafe -count;
47
}
58

6-
class NSMutableArray: Owned {
7-
unsafe mut -removeAllObjects;
8-
mut -addObject;
9-
mut -insertObject_atIndex;
10-
mut -replaceObjectAtIndex_withObject;
11-
mut -removeObjectAtIndex;
12-
mut -removeLastObject;
13-
mut -sortUsingFunction_context;
9+
class NSMutableArray: MutableWithImmutableSuperclass<Foundation::NSArray> {
10+
unsafe -removeAllObjects;
1411
}
1512

16-
class NSString {
13+
class NSString: ImmutableWithMutableSubclass<Foundation::NSMutableString> {
1714
unsafe -init;
1815
unsafe -compare;
1916
unsafe -hasPrefix;
@@ -30,59 +27,66 @@ data! {
3027
unsafe +stringWithString;
3128
}
3229

33-
class NSMutableString: Owned {
30+
class NSMutableString: MutableWithImmutableSuperclass<Foundation::NSString> {
3431
unsafe -initWithCapacity;
3532
unsafe +stringWithCapacity;
3633
unsafe -initWithString;
3734
unsafe +stringWithString;
38-
unsafe mut -appendString;
39-
unsafe mut -setString;
35+
unsafe -appendString;
36+
unsafe -setString;
4037
}
4138

42-
class NSAttributedString {
39+
// Allowed to be just `Immutable` since we've removed the `NSCopying` and
40+
// `NSMutableCopying` impls from these for now (they'd return the wrong
41+
// type).
42+
class NSSimpleCString: Immutable {}
43+
class NSConstantString: Immutable {}
44+
45+
class NSAttributedString: ImmutableWithMutableSubclass<Foundation::NSMutableAttributedString> {
4346
unsafe -initWithString;
4447
unsafe -initWithAttributedString;
4548
unsafe -string;
4649
unsafe -length;
4750
}
4851

49-
class NSMutableAttributedString: Owned {
52+
class NSMutableAttributedString: MutableWithImmutableSuperclass<Foundation::NSAttributedString> {
5053
unsafe -initWithString;
5154
unsafe -initWithAttributedString;
52-
unsafe mut -setAttributedString;
55+
unsafe -setAttributedString;
5356
}
5457

5558
class NSBundle {
5659
unsafe +mainBundle;
5760
unsafe -infoDictionary;
5861
}
5962

60-
class NSData {
63+
class NSData: ImmutableWithMutableSubclass<Foundation::NSMutableData> {
6164
unsafe -initWithData;
6265
unsafe +dataWithData;
6366
unsafe -length;
6467
unsafe -bytes;
6568
}
6669

67-
class NSMutableData: Owned {
70+
class NSMutableData: MutableWithImmutableSuperclass<Foundation::NSData> {
6871
unsafe +dataWithData;
6972
unsafe -initWithCapacity;
7073
unsafe +dataWithCapacity;
71-
unsafe mut -setLength;
72-
unsafe mut -mutableBytes;
74+
unsafe -setLength;
75+
unsafe -mutableBytes;
7376
}
7477

75-
class NSDictionary {
78+
// Allowed to be just `Mutable` since we've removed the `NSCopying` and
79+
// `NSMutableCopying` impls from this for now (since they'd return the
80+
// wrong type).
81+
class NSPurgeableData: Mutable {}
82+
83+
class NSDictionary: ImmutableWithMutableSubclass<Foundation::NSMutableDictionary> {
7684
unsafe -count;
77-
unsafe -objectForKey;
78-
unsafe -allKeys;
79-
unsafe -allValues;
8085
}
8186

82-
class NSMutableDictionary: Owned {
83-
unsafe mut -setDictionary;
84-
unsafe mut -removeObjectForKey;
85-
unsafe mut -removeAllObjects;
87+
class NSMutableDictionary: MutableWithImmutableSuperclass<Foundation::NSDictionary> {
88+
unsafe -removeObjectForKey;
89+
unsafe -removeAllObjects;
8690
}
8791

8892
class NSError {
@@ -130,20 +134,22 @@ data! {
130134
unsafe -operatingSystemVersion;
131135
}
132136

133-
class NSSet {
137+
class NSSet: ImmutableWithMutableSubclass<Foundation::NSMutableSet> {
134138
unsafe -count;
135139
}
136140

137-
class NSMutableSet: Owned {
138-
unsafe mut -removeAllObjects;
139-
mut -addObject;
141+
class NSMutableSet: MutableWithImmutableSuperclass<Foundation::NSSet> {
142+
unsafe -removeAllObjects;
140143
}
141144

142-
class NSMutableCharacterSet: Owned {}
145+
class NSCharacterSet: ImmutableWithMutableSubclass<Foundation::NSMutableCharacterSet> {}
146+
class NSMutableCharacterSet: MutableWithImmutableSuperclass<Foundation::NSCharacterSet> {}
143147

144-
class NSMutableOrderedSet: Owned {}
148+
class NSOrderedSet: ImmutableWithMutableSubclass<Foundation::NSMutableOrderedSet> {}
149+
class NSMutableOrderedSet: MutableWithImmutableSuperclass<Foundation::NSOrderedSet> {}
145150

146-
class NSMutableIndexSet: Owned {}
151+
class NSIndexSet: ImmutableWithMutableSubclass<Foundation::NSMutableIndexSet> {}
152+
class NSMutableIndexSet: MutableWithImmutableSuperclass<Foundation::NSIndexSet> {}
147153

148154
class NSNumber {
149155
unsafe -initWithChar;
@@ -196,5 +202,6 @@ data! {
196202
unsafe -stringValue;
197203
}
198204

199-
class NSMutableURLRequest: Owned {}
205+
class NSURLRequest: ImmutableWithMutableSubclass<Foundation::NSMutableURLRequest> {}
206+
class NSMutableURLRequest: MutableWithImmutableSuperclass<Foundation::NSURLRequest> {}
200207
}

crates/header-translator/src/data/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,16 @@ marked safe, so such an improvement can be made in a minor version!
4141

4242
```rust , ignore
4343
data! {
44-
// Everywhere that the class is returned, it is as
45-
// `Id<MyMutableClass, Owned>`.
46-
//
47-
// Specifying this is _not_ unsafe, but every method that returns this
48-
// class must be checked for safety with it in mind.
49-
class MyMutableClass: Owned {
44+
class MyClass {
5045
// The class method `new` is safe.
5146
unsafe +new;
5247
// The method `init` is safe.
5348
unsafe -init;
49+
}
50+
51+
class MyImmutableClass: ImmutableWithMutableSubclass<MyMutableClass> {}
52+
53+
class MyMutableClass: MutableWithImmutableSuperclass<MyImmutableClass> {
5454
// The method `mutate` takes &mut self, and is safe.
5555
unsafe mut -mutate;
5656
// The method `mutateUnchecked` takes &mut self, but is not safe.

0 commit comments

Comments
 (0)