Skip to content

Commit 4e64c1a

Browse files
authored
Merge pull request #521 from madsmtm/redo-ivars
Redo instance variables
2 parents 71bd307 + 2d188cb commit 4e64c1a

File tree

79 files changed

+5012
-6623
lines changed

Some content is hidden

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

79 files changed

+5012
-6623
lines changed

Cargo.lock

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

crates/icrate/examples/browser.rs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![deny(unsafe_op_in_unsafe_fn)]
2-
use core::{cell::OnceCell, ptr::NonNull};
2+
use core::cell::OnceCell;
33

44
#[allow(deprecated)]
55
use icrate::{
@@ -19,26 +19,23 @@ use icrate::{
1919
WebKit::{WKNavigation, WKNavigationDelegate, WKWebView},
2020
};
2121
use objc2::{
22-
declare::{Ivar, IvarDrop},
23-
declare_class, msg_send, msg_send_id,
22+
declare_class, msg_send_id,
2423
mutability::MainThreadOnly,
2524
rc::Id,
2625
runtime::{AnyObject, ProtocolObject, Sel},
27-
sel, ClassType,
26+
sel, ClassType, DeclaredClass,
2827
};
2928

30-
type IdCell<T> = Box<OnceCell<Id<T>>>;
31-
3229
macro_rules! idcell {
3330
($name:ident => $this:expr) => {
34-
$this.$name.set($name).expect(&format!(
31+
$this.ivars().$name.set($name).expect(&format!(
3532
"ivar should not already be initialized: `{}`",
3633
stringify!($name)
3734
));
3835
};
3936
($name:ident <= $this:expr) => {
4037
#[rustfmt::skip]
41-
let Some($name) = $this.$name.get() else {
38+
let Some($name) = $this.ivars().$name.get() else {
4239
unreachable!(
4340
"ivar should be initialized: `{}`",
4441
stringify!($name)
@@ -47,31 +44,28 @@ macro_rules! idcell {
4744
};
4845
}
4946

47+
#[derive(Default)]
48+
struct Ivars {
49+
nav_url: OnceCell<Id<NSTextField>>,
50+
web_view: OnceCell<Id<WKWebView>>,
51+
window: OnceCell<Id<NSWindow>>,
52+
}
53+
5054
declare_class!(
51-
struct Delegate {
52-
nav_url: IvarDrop<IdCell<NSTextField>, "_nav_url">,
53-
web_view: IvarDrop<IdCell<WKWebView>, "_web_view">,
54-
window: IvarDrop<IdCell<NSWindow>, "_window">,
55-
}
56-
mod ivars;
55+
struct Delegate;
5756

57+
// SAFETY:
58+
// - The superclass NSObject does not have any subclassing requirements.
59+
// - Main thread only mutability is correct, since this is an application delegate.
60+
// - `Delegate` does not implement `Drop`.
5861
unsafe impl ClassType for Delegate {
5962
type Super = NSObject;
6063
type Mutability = MainThreadOnly;
6164
const NAME: &'static str = "Delegate";
6265
}
6366

64-
unsafe impl Delegate {
65-
#[method(init)]
66-
unsafe fn init(this: *mut Self) -> Option<NonNull<Self>> {
67-
let this: Option<&mut Self> = msg_send![super(this), init];
68-
this.map(|this| {
69-
Ivar::write(&mut this.nav_url, IdCell::default());
70-
Ivar::write(&mut this.web_view, IdCell::default());
71-
Ivar::write(&mut this.window, IdCell::default());
72-
NonNull::from(this)
73-
})
74-
}
67+
impl DeclaredClass for Delegate {
68+
type Ivars = Ivars;
7569
}
7670

7771
unsafe impl NSObjectProtocol for Delegate {}
@@ -298,7 +292,9 @@ declare_class!(
298292

299293
impl Delegate {
300294
pub fn new(mtm: MainThreadMarker) -> Id<Self> {
301-
unsafe { msg_send_id![mtm.alloc(), init] }
295+
let this = mtm.alloc();
296+
let this = this.set_ivars(Ivars::default());
297+
unsafe { msg_send_id![super(this), init] }
302298
}
303299
}
304300

@@ -307,10 +303,8 @@ fn main() {
307303
let app = NSApplication::sharedApplication(mtm);
308304
app.setActivationPolicy(NSApplicationActivationPolicyRegular);
309305

310-
// initialize the delegate
311-
let delegate = Delegate::new(mtm);
312-
313306
// configure the application delegate
307+
let delegate = Delegate::new(mtm);
314308
let object = ProtocolObject::from_ref(&*delegate);
315309
app.setDelegate(Some(object));
316310

crates/icrate/examples/delegate.rs

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,38 @@
11
#![deny(unsafe_op_in_unsafe_fn)]
2-
use std::ptr::NonNull;
3-
42
use icrate::AppKit::{NSApplication, NSApplicationActivationPolicyRegular, NSApplicationDelegate};
53
use icrate::Foundation::{
64
ns_string, MainThreadMarker, NSCopying, NSNotification, NSObject, NSObjectProtocol, NSString,
75
};
8-
use objc2::declare::{Ivar, IvarBool, IvarDrop, IvarEncode};
96
use objc2::rc::Id;
107
use objc2::runtime::ProtocolObject;
11-
use objc2::{declare_class, msg_send, msg_send_id, mutability, ClassType};
8+
use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass};
9+
10+
#[derive(Debug)]
11+
#[allow(unused)]
12+
struct Ivars {
13+
ivar: u8,
14+
another_ivar: bool,
15+
box_ivar: Box<i32>,
16+
maybe_box_ivar: Option<Box<i32>>,
17+
id_ivar: Id<NSString>,
18+
maybe_id_ivar: Option<Id<NSString>>,
19+
}
1220

1321
declare_class!(
14-
#[derive(Debug)]
15-
struct AppDelegate {
16-
ivar: IvarEncode<u8, "_ivar">,
17-
another_ivar: IvarBool<"_another_ivar">,
18-
box_ivar: IvarDrop<Box<i32>, "_box_ivar">,
19-
maybe_box_ivar: IvarDrop<Option<Box<i32>>, "_maybe_box_ivar">,
20-
id_ivar: IvarDrop<Id<NSString>, "_id_ivar">,
21-
maybe_id_ivar: IvarDrop<Option<Id<NSString>>, "_maybe_id_ivar">,
22-
}
23-
24-
mod ivars;
22+
struct AppDelegate;
2523

24+
// SAFETY:
25+
// - The superclass NSObject does not have any subclassing requirements.
26+
// - Main thread only mutability is correct, since this is an application delegate.
27+
// - `AppDelegate` does not implement `Drop`.
2628
unsafe impl ClassType for AppDelegate {
2729
type Super = NSObject;
2830
type Mutability = mutability::MainThreadOnly;
2931
const NAME: &'static str = "MyAppDelegate";
3032
}
3133

32-
unsafe impl AppDelegate {
33-
#[method(initWith:another:)]
34-
unsafe fn init_with(
35-
this: *mut Self,
36-
ivar: u8,
37-
another_ivar: bool,
38-
) -> Option<NonNull<Self>> {
39-
let this: Option<&mut Self> = unsafe { msg_send![super(this), init] };
40-
41-
this.map(|this| {
42-
Ivar::write(&mut this.ivar, ivar);
43-
Ivar::write(&mut this.another_ivar, another_ivar);
44-
Ivar::write(&mut this.maybe_box_ivar, None);
45-
Ivar::write(&mut this.maybe_id_ivar, Some(ns_string!("def").copy()));
46-
Ivar::write(&mut this.box_ivar, Box::new(2));
47-
Ivar::write(&mut this.id_ivar, NSString::from_str("abc"));
48-
NonNull::from(this)
49-
})
50-
}
34+
impl DeclaredClass for AppDelegate {
35+
type Ivars = Ivars;
5136
}
5237

5338
unsafe impl NSObjectProtocol for AppDelegate {}
@@ -69,7 +54,16 @@ declare_class!(
6954

7055
impl AppDelegate {
7156
pub fn new(ivar: u8, another_ivar: bool, mtm: MainThreadMarker) -> Id<Self> {
72-
unsafe { msg_send_id![mtm.alloc(), initWith: ivar, another: another_ivar] }
57+
let this = mtm.alloc();
58+
let this = this.set_ivars(Ivars {
59+
ivar,
60+
another_ivar,
61+
box_ivar: Box::new(2),
62+
maybe_box_ivar: None,
63+
id_ivar: NSString::from_str("abc"),
64+
maybe_id_ivar: Some(ns_string!("def").copy()),
65+
});
66+
unsafe { msg_send_id![super(this), init] }
7367
}
7468
}
7569

@@ -79,12 +73,8 @@ fn main() {
7973
let app = NSApplication::sharedApplication(mtm);
8074
app.setActivationPolicy(NSApplicationActivationPolicyRegular);
8175

82-
// initialize the delegate
83-
let delegate = AppDelegate::new(42, true, mtm);
84-
85-
println!("{delegate:?}");
86-
8776
// configure the application delegate
77+
let delegate = AppDelegate::new(42, true, mtm);
8878
let object = ProtocolObject::from_ref(&*delegate);
8979
app.setDelegate(Some(object));
9080

crates/icrate/examples/metal.rs

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,8 @@ use icrate::{
2020
MetalKit::{MTKView, MTKViewDelegate},
2121
};
2222
use objc2::{
23-
declare::{Ivar, IvarDrop},
24-
declare_class, msg_send, msg_send_id,
25-
mutability::MainThreadOnly,
26-
rc::Id,
27-
runtime::ProtocolObject,
28-
ClassType,
23+
declare_class, msg_send_id, mutability::MainThreadOnly, rc::Id, runtime::ProtocolObject,
24+
ClassType, DeclaredClass,
2925
};
3026

3127
#[rustfmt::skip]
@@ -101,18 +97,16 @@ pub struct Color {
10197
pub b: f32,
10298
}
10399

104-
type IdCell<T> = Box<OnceCell<Id<T>>>;
105-
106100
macro_rules! idcell {
107101
($name:ident => $this:expr) => {
108-
$this.$name.set($name).expect(&format!(
102+
$this.ivars().$name.set($name).expect(&format!(
109103
"ivar should not already be initialized: `{}`",
110104
stringify!($name)
111105
));
112106
};
113107
($name:ident <= $this:expr) => {
114108
#[rustfmt::skip]
115-
let Some($name) = $this.$name.get() else {
109+
let Some($name) = $this.ivars().$name.get() else {
116110
unreachable!(
117111
"ivar should be initialized: `{}`",
118112
stringify!($name)
@@ -121,38 +115,30 @@ macro_rules! idcell {
121115
};
122116
}
123117

118+
// declare the desired instance variables
119+
struct Ivars {
120+
start_date: Id<NSDate>,
121+
command_queue: OnceCell<Id<ProtocolObject<dyn MTLCommandQueue>>>,
122+
pipeline_state: OnceCell<Id<ProtocolObject<dyn MTLRenderPipelineState>>>,
123+
window: OnceCell<Id<NSWindow>>,
124+
}
125+
124126
// declare the Objective-C class machinery
125127
declare_class!(
126-
// declare the delegate class with our instance variables
127-
#[rustfmt::skip] // FIXME: rustfmt breaks the macro parsing apparently
128-
struct Delegate {
129-
start_date: IvarDrop<Id<NSDate>, "_start_date">,
130-
command_queue: IvarDrop<IdCell<ProtocolObject<dyn MTLCommandQueue>>, "_command_queue">,
131-
pipeline_state: IvarDrop<IdCell<ProtocolObject<dyn MTLRenderPipelineState>>, "_pipeline_state">,
132-
window: IvarDrop<IdCell<NSWindow>, "_window">,
133-
}
134-
mod ivars;
128+
struct Delegate;
135129

136-
// declare the class type
130+
// SAFETY:
131+
// - The superclass NSObject does not have any subclassing requirements.
132+
// - Main thread only mutability is correct, since this is an application delegate.
133+
// - `Delegate` does not implement `Drop`.
137134
unsafe impl ClassType for Delegate {
138135
type Super = NSObject;
139136
type Mutability = MainThreadOnly;
140137
const NAME: &'static str = "Delegate";
141138
}
142139

143-
// define the Delegate methods (e.g., initializer)
144-
unsafe impl Delegate {
145-
#[method(init)]
146-
unsafe fn init(this: *mut Self) -> Option<NonNull<Self>> {
147-
let this: Option<&mut Self> = msg_send![super(this), init];
148-
this.map(|this| {
149-
Ivar::write(&mut this.start_date, unsafe { NSDate::now() });
150-
Ivar::write(&mut this.command_queue, IdCell::default());
151-
Ivar::write(&mut this.pipeline_state, IdCell::default());
152-
Ivar::write(&mut this.window, IdCell::default());
153-
NonNull::from(this)
154-
})
155-
}
140+
impl DeclaredClass for Delegate {
141+
type Ivars = Ivars;
156142
}
157143

158144
unsafe impl NSObjectProtocol for Delegate {}
@@ -277,7 +263,7 @@ declare_class!(
277263

278264
// compute the scene properties
279265
let scene_properties_data = &SceneProperties {
280-
time: unsafe { self.start_date.timeIntervalSinceNow() } as f32,
266+
time: unsafe { self.ivars().start_date.timeIntervalSinceNow() } as f32,
281267
};
282268
// write the scene properties to the vertex shader argument buffer at index 0
283269
let scene_properties_bytes = NonNull::from(scene_properties_data);
@@ -360,7 +346,14 @@ declare_class!(
360346

361347
impl Delegate {
362348
pub fn new(mtm: MainThreadMarker) -> Id<Self> {
363-
unsafe { msg_send_id![mtm.alloc(), init] }
349+
let this = mtm.alloc();
350+
let this = this.set_ivars(Ivars {
351+
start_date: unsafe { NSDate::now() },
352+
command_queue: OnceCell::default(),
353+
pipeline_state: OnceCell::default(),
354+
window: OnceCell::default(),
355+
});
356+
unsafe { msg_send_id![super(this), init] }
364357
}
365358
}
366359

@@ -370,10 +363,8 @@ fn main() {
370363
let app = NSApplication::sharedApplication(mtm);
371364
app.setActivationPolicy(NSApplicationActivationPolicyRegular);
372365

373-
// initialize the delegate
374-
let delegate = Delegate::new(mtm);
375-
376366
// configure the application delegate
367+
let delegate = Delegate::new(mtm);
377368
let object = ProtocolObject::from_ref(&*delegate);
378369
app.setDelegate(Some(object));
379370

crates/icrate/tests/array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn test_retains_stored() {
122122

123123
drop(obj);
124124
expected.release += 1;
125-
expected.dealloc += 1;
125+
expected.drop += 1;
126126
expected.assert_current();
127127
}
128128

@@ -187,7 +187,7 @@ fn test_iter_minimal_retains() {
187187

188188
assert_eq!(iter.count(), 0);
189189
expected.release += 1;
190-
expected.dealloc += 1;
190+
expected.drop += 1;
191191
expected.assert_current();
192192
}
193193

0 commit comments

Comments
 (0)