core-foundation-rs
core-foundation-rs copied to clipboard
Replace `objc` with `objc2`?
Hey, macOS maintainer of winit
here!
I've been working on a replacement for objc
for around a year now, and am finally getting close to something I'm happy with, see repo, docs and reasons for fork.
The selling point for your crates (cocoa
and cocoa-foundation
) is... Honestly not as strong as I'd like, my improvements mostly benefit higher-level crates and users that try to make a safer API, and your crates don't really do safe. That said, there are reasons, and I think they are enough to outweigh the downsides. I'm opening this PR to get some thoughts on what it would take for you to make the switch, would love to get some feedback!
Concrete improvements that directly benefit you:
- Using the
"verify_message"
feature (planning to enable it withdebug_assertions
) now works, which is why we implementEncode
for a lot of types - this is great for catching bugs, see the first commit in this PR for a few issues I found using this. - Fixed soundness issues concerning message sending, namely:
- Stop dereferencing the receiver - This means that sending messages to NULL is no longer immediate UB.
-
Make
Object
store anUnsafeCell
- This enables interior mutability ofObject
, meaning that if user code had a&Object
, converted that to*mut Object
and sent a mutating message, this would not be immediate UB. -
Don't try to access the receiver behind
&
- Might not be sound to accessid
behind&id
even ifObject
containsUnsafeCell
- A bit more theoretical, but every bit helps!
- Easier way of making methods take and return
bool
instead ofBOOL
(done in follow-up PR) -
NSInteger
/NSUInteger
is nowisize
/usize
(done in follow-up PR) - Greatly improved docs for
msg_send!
, hopefully new contributors will be less confused. - Static selectors (users can opt-in using
"unstable-static-sel"
feature flag for now).
Future improvements that could benefit you (if one of these would be the tipping point for wanting to make the switch, please state so):
-
A way to make a retainable object that doesn't guarantee the mutability of the pointer, this would allow your crates to easily follow Cocoa's memory model using
msg_send_id!
. Examples: You have to manually callrelease
on the object gotten from+[NSWindow alloc]
+init
and-[NSMenuItem separatorItem]
returns an autoreleased object that really needs to beretain
'ed before use. -
derive(Encode, RefEncode)
macro so we don't need to do it ourselves, which is error-prone. Not sure what you would think regarding the compile-time cost, so I went for defining a local helper macroimpl_Encode
instead. -
objc2
bindgen
support so that thecocoa
crate doesn't have to be written manually any more.
Downsides:
-
Ecosystem split. I intend to submit PRs to a lot of the popular crates using
objc
to help this along! - Breaking changes. I've tried to keep it as simple a replacement as possible though, so not as big an issue as one would expect.
- New, while it builds upon
objc
it has still seen less real-world usage. - Will probably see a bit more frequent releases (I may have to do a breaking release or two until I'm satisfied with the API). Trying to prevent this by opening PRs and gathering feedback first!
- No MSRV policy (please provide input here!)
Breaking changes (apart from the obvious "new crate, new types"):
-
Object
is no longerSend
orSync
, since it may be used to represent objects that aren't (likeNSAutoreleasePool
andNSLock
). - Methods now take and return
bool
instead ofBOOL
(follow-up PR) -
NSInteger
/NSUInteger
is nowisize
/usize
(follow-up PR)
A lot of this is written assuming intimate knowledge of the existing objc
crate, happy to answer any questions you might have if something is unclear!
EDIT: Have added static selectors now.
Regarding compile-times, did a quick check, a clean build seems to be about the same (~14s) for cocoa
- objc2
uses objc-sys
, which has a build script, but on the other hand it doesn't depend on libc
, which allows for more parallelism.
A clean build of winit
regressed slightly (from ~16s to ~18s on my machine).
:umbrella: The latest upstream changes (presumably #508) made this pull request unmergeable. Please resolve the merge conflicts.
I looked a little at objc2 last night and think it's overall the right direction to be heading in. My opinion here is based on reviewing https://github.com/gfx-rs/wgpu/pull/2826/files and the need for https://github.com/gfx-rs/wgpu/pull/2976.
objc2 is definitely a lot more complex so I haven't had a chance to look at any details yet.
I think there's a lot of potential in making things even more ergonomic, but I'll be experimenting with that in cacao
first (especially msg_send_id!
for imitating Objective-C ARC is promising).
I'll try to write a bit more introductory text at some point, to make the differences between objc
and objc2
clearer for newcomers.
Also, at some point I'll probably submit a similar PR to this one to metal
and wgpu
to improve the situation there.