Skip to content

Commit c8a2ed2

Browse files
committed
WIP
msg_send_id![super]
1 parent cedec25 commit c8a2ed2

File tree

72 files changed

+4842
-4815
lines changed

Some content is hidden

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

72 files changed

+4842
-4815
lines changed

crates/icrate/examples/browser.rs

Lines changed: 22 additions & 24 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
use icrate::{
55
AppKit::{
@@ -18,26 +18,23 @@ use icrate::{
1818
WebKit::{WKNavigation, WKNavigationDelegate, WKWebView},
1919
};
2020
use objc2::{
21-
declare::{Ivar, IvarDrop},
22-
declare_class, msg_send, msg_send_id,
21+
declare_class, msg_send_id,
2322
mutability::MainThreadOnly,
24-
rc::Id,
23+
rc::{Allocated, Id},
2524
runtime::{AnyObject, ProtocolObject, Sel},
26-
sel, ClassType,
25+
sel, ClassType, DeclaredClass,
2726
};
2827

29-
type IdCell<T> = Box<OnceCell<Id<T>>>;
30-
3128
macro_rules! idcell {
3229
($name:ident => $this:expr) => {
33-
$this.$name.set($name).expect(&format!(
30+
$this.ivars().$name.set($name).expect(&format!(
3431
"ivar should not already be initialized: `{}`",
3532
stringify!($name)
3633
));
3734
};
3835
($name:ident <= $this:expr) => {
3936
#[rustfmt::skip]
40-
let Some($name) = $this.$name.get() else {
37+
let Some($name) = $this.ivars().$name.get() else {
4138
unreachable!(
4239
"ivar should be initialized: `{}`",
4340
stringify!($name)
@@ -46,30 +43,31 @@ macro_rules! idcell {
4643
};
4744
}
4845

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

5756
unsafe impl ClassType for Delegate {
5857
type Super = NSObject;
5958
type Mutability = MainThreadOnly;
6059
const NAME: &'static str = "Delegate";
6160
}
6261

62+
impl DeclaredClass for Delegate {
63+
type Ivars = Ivars;
64+
}
65+
6366
unsafe impl Delegate {
64-
#[method(init)]
65-
unsafe fn init(this: *mut Self) -> Option<NonNull<Self>> {
66-
let this: Option<&mut Self> = msg_send![super(this), init];
67-
this.map(|this| {
68-
Ivar::write(&mut this.nav_url, IdCell::default());
69-
Ivar::write(&mut this.web_view, IdCell::default());
70-
Ivar::write(&mut this.window, IdCell::default());
71-
NonNull::from(this)
72-
})
67+
#[method_id(init)]
68+
fn init(this: Allocated<Self>) -> Option<Id<Self>> {
69+
let this = this.set_ivars(Ivars::default());
70+
unsafe { msg_send_id![super(this), init] }
7371
}
7472
}
7573

crates/icrate/examples/delegate.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,52 @@
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};
9-
use objc2::rc::Id;
6+
use objc2::rc::{Allocated, 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!(
1422
#[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;
23+
struct AppDelegate;
2524

2625
unsafe impl ClassType for AppDelegate {
2726
type Super = NSObject;
2827
type Mutability = mutability::MainThreadOnly;
2928
const NAME: &'static str = "MyAppDelegate";
3029
}
3130

31+
impl DeclaredClass for AppDelegate {
32+
type Ivars = Ivars;
33+
}
34+
3235
unsafe impl AppDelegate {
33-
#[method(initWith:another:)]
34-
unsafe fn init_with(
35-
this: *mut Self,
36+
#[method_id(initWith:another:)]
37+
fn init_with(
38+
this: Allocated<Self>,
3639
ivar: u8,
3740
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-
})
41+
) -> Option<Id<Self>> {
42+
let this = this.set_ivars(Ivars {
43+
ivar,another_ivar,
44+
box_ivar: Box::new(2),
45+
maybe_box_ivar: None,
46+
id_ivar: NSString::from_str("abc"),
47+
maybe_id_ivar: Some(ns_string!("def").copy()),
48+
});
49+
unsafe { msg_send_id![super(this), init] }
5050
}
5151
}
5252

crates/icrate/examples/metal.rs

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

3130
#[rustfmt::skip]
@@ -101,18 +100,16 @@ pub struct Color {
101100
pub b: f32,
102101
}
103102

104-
type IdCell<T> = Box<OnceCell<Id<T>>>;
105-
106103
macro_rules! idcell {
107104
($name:ident => $this:expr) => {
108-
$this.$name.set($name).expect(&format!(
105+
$this.ivars().$name.set($name).expect(&format!(
109106
"ivar should not already be initialized: `{}`",
110107
stringify!($name)
111108
));
112109
};
113110
($name:ident <= $this:expr) => {
114111
#[rustfmt::skip]
115-
let Some($name) = $this.$name.get() else {
112+
let Some($name) = $this.ivars().$name.get() else {
116113
unreachable!(
117114
"ivar should be initialized: `{}`",
118115
stringify!($name)
@@ -121,17 +118,17 @@ macro_rules! idcell {
121118
};
122119
}
123120

121+
// declare the desired instance variables
122+
struct Ivars {
123+
start_date: Id<NSDate>,
124+
command_queue: OnceCell<Id<ProtocolObject<dyn MTLCommandQueue>>>,
125+
pipeline_state: OnceCell<Id<ProtocolObject<dyn MTLRenderPipelineState>>>,
126+
window: OnceCell<Id<NSWindow>>,
127+
}
128+
124129
// declare the Objective-C class machinery
125130
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;
131+
struct Delegate;
135132

136133
// declare the class type
137134
unsafe impl ClassType for Delegate {
@@ -140,18 +137,21 @@ declare_class!(
140137
const NAME: &'static str = "Delegate";
141138
}
142139

140+
impl DeclaredClass for Delegate {
141+
type Ivars = Ivars;
142+
}
143+
143144
// define the Delegate methods (e.g., initializer)
144145
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-
})
146+
#[method_id(init)]
147+
fn init(this: Allocated<Self>) -> Option<Id<Self>> {
148+
let this = this.set_ivars(Ivars {
149+
start_date: unsafe { NSDate::now() },
150+
command_queue: OnceCell::default(),
151+
pipeline_state: OnceCell::default(),
152+
window: OnceCell::default(),
153+
});
154+
unsafe { msg_send_id![super(this), init] }
155155
}
156156
}
157157

@@ -277,7 +277,7 @@ declare_class!(
277277

278278
// compute the scene properties
279279
let scene_properties_data = &SceneProperties {
280-
time: unsafe { self.start_date.timeIntervalSinceNow() } as f32,
280+
time: unsafe { self.ivars().start_date.timeIntervalSinceNow() } as f32,
281281
};
282282
// write the scene properties to the vertex shader argument buffer at index 0
283283
let scene_properties_bytes = NonNull::from(scene_properties_data);

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ extern_protocol!(
3434
/// # Safety
3535
///
3636
/// The zone pointer must be valid or NULL.
37+
///
38+
///
39+
/// # Examples
40+
///
41+
/// Examples on how to implement copyWithZone:
42+
///
43+
/// TODO
44+
///
45+
/// The different ways described in apples doc
3746
#[method_id(copyWithZone:)]
3847
unsafe fn copyWithZone(&self, zone: *mut NSZone) -> Id<Self::Immutable>
3948
where

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

crates/icrate/tests/auto_traits.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use icrate::Foundation::*;
77
use objc2::mutability::{Immutable, Mutable};
88
use objc2::rc::Id;
99
use objc2::runtime::AnyObject;
10-
use objc2::{declare_class, ClassType};
10+
use objc2::{declare_class, ClassType, DeclaredClass};
1111

1212
// We expect most Foundation types to be UnwindSafe and RefUnwindSafe,
1313
// since they follow Rust's usual mutability rules (&T = immutable).
@@ -40,6 +40,8 @@ macro_rules! helper {
4040
type Mutability = $mutability;
4141
const NAME: &'static str = concat!(stringify!($name), "Test");
4242
}
43+
44+
impl DeclaredClass for $name {}
4345
);
4446
};
4547
}

crates/icrate/tests/mutable_array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ fn test_remove() {
151151

152152
array.removeAllObjects();
153153
expected.release += 2;
154-
expected.dealloc += 2;
154+
expected.drop += 2;
155155
expected.assert_current();
156156
assert_eq!(array.len(), 0);
157157
}

crates/icrate/tests/mutable_dictionary.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn test_insert_key_copies() {
102102
dict.removeAllObjects();
103103
// Release key
104104
expected.release += 1;
105-
expected.dealloc += 1;
105+
expected.drop += 1;
106106
expected.assert_current();
107107
}
108108

@@ -137,7 +137,7 @@ fn test_insert_value_retain_release() {
137137

138138
drop(old);
139139
expected.release += 1;
140-
expected.dealloc += 1;
140+
expected.drop += 1;
141141
expected.assert_current();
142142
}
143143

@@ -183,7 +183,7 @@ fn test_remove_clear_release_dealloc() {
183183

184184
dict.removeAllObjects();
185185
expected.release += 2;
186-
expected.dealloc += 2;
186+
expected.drop += 2;
187187
expected.assert_current();
188188
assert_eq!(dict.len(), 0);
189189
}

crates/icrate/tests/mutable_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fn test_clear_release_dealloc() {
113113

114114
set.removeAllObjects();
115115
expected.release += 4;
116-
expected.dealloc += 4;
116+
expected.drop += 4;
117117
expected.assert_current();
118118
assert_eq!(set.len(), 0);
119119
}

crates/icrate/tests/set.rs

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

228228
drop(obj);
229229
expected.release += 1;
230-
expected.dealloc += 1;
230+
expected.drop += 1;
231231
expected.assert_current();
232232
}
233233

@@ -291,7 +291,7 @@ fn test_iter_minimal_retains() {
291291

292292
assert_eq!(iter.count(), 0);
293293
expected.release += 1;
294-
expected.dealloc += 1;
294+
expected.drop += 1;
295295
expected.assert_current();
296296
}
297297

0 commit comments

Comments
 (0)