-
Notifications
You must be signed in to change notification settings - Fork 237
Description
Hey @waywardmonkeys, @jrmuizel, @mrobinson and @wusyong (and CC @tmandry and @simlay).
Over the past few years, I've been working on replacements for the crates in this repo in the objc2 project, see #513 and #628 for some previous discussion. To rehash the benefits of the objc2-* crates:
- Code generation from headers, which means that basically every upstream API is available (only a few explicitly skipped APIs aren't), and this will remain true even as Apple releases new SDK versions over time (since we only need to rerun the generator).
- Automatic memory management, all objects are wrapped by the code generator in either
objc2::rc::Retainedorobjc2_core_foundation::CFRetained, which will release the object onDrop. The generator knows about the "create rule" and about opt-outs likeCF_RETURNS_NOT_RETAINEDetc. (so it will do this correctly with a much higher probability than if a human did it). - Type-safety, especially compared to
cocoaandcocoa-foundationwhere everything is just an extension trait on theidpointer.
I'm motivated in bringing these benefits to the entirety of the Apple+Rust ecosystem, as I think the soundness, correctness and ergonomics improvements here are quite significant. To that end, I've been slowly migrating major Rust projects, see madsmtm/objc2#174.
A recent milestone is that I've released objc2-core-foundation v0.3.1, which I believe now covers everything that core-foundation does! I've also assessed every open issue and pull-request in this repo, and made sure that they're either resolved or tracked in the objc2 repo, see madsmtm/objc2#719. So at this point, I'd like to start discussing the future of this project, and how we can migrate Servo and other users to the objc2-* crates (assuming you agree that's a goal, if not then I'd also like to discuss that!)
My ideal scenario would be that the crates in this repo were marked #![deprecated] with re-exports of the objc2-* variants, both to give users an easier migration path, and because in a way it'd "bless" the objc2 crates, but I can see other solutions, including any of the following variations:
- Only do this for
cocoaandcocoa-foundation(these are whereobjc2-*would be the most valuable). - Soft-deprecate the crates in the README only, but without actually marking it
#![deprecated]. - Publish an advisory to the RUSTSEC advisory database (my own preference would be not to, at least not yet).
A few drawbacks to consider:
- It is a fair amount of churn. I don't believe it to be unnecessary churn though, there really are a lot of bugs out there in Apple+Rust-related code, and a lot of them could be alleviated with the
objc2-*crates. objc2-*crates are a bit less stable thancore-foundation-rscrates. I do tend to be conservative of breaking changes, and to plan ahead to allow spacing them out as much as possible.- It is my understanding that Firefox/Mozilla vets/audits every dependency, and that the
objc2-*crates haven't been audited, so this might hurt them until that happens? CC @ErichDonGubler and @jimblandy maybe? - This could be seen as a supply-chain attack. Don't know how to alleviate that, other than having people review my code ;)
- Bus factor,
objc2has fewer maintainers. I'd love to get others on board though, just say so if you want to! Or join the Matrix workspace to start with.
Crate status / comparison
Note that I'm not entirely done transitioning things here, see the below table for the current status (which is probably slightly incorrect, there's bound to be something I've missed):
| Servo crate | objc2 crate |
Comparison |
|---|---|---|
cocoa |
objc2-app-kit |
Fully superseded ✅ |
cocoa-foundation |
objc2-foundation |
Fully superseded ✅ |
core-foundation-sys |
objc2-core-foundation |
Fully superseded ✅ |
core-foundation |
objc2-core-foundation |
Fully superseded ✅ |
core-graphics-types |
objc2-core-foundation |
Fully superseded ✅ |
core-graphics |
objc2-core-graphics |
Missing CGDirectDisplayID wrapper and most functions are still unsafe |
core-text |
objc2-core-text |
Still a fair bit of work to do to make it as nice ❗️ |
io-surface |
objc2-io-surface |
Fully superseded ✅ |
But I do intend to resolve this, so I still feel it's valuable to start discussing migration now.
How objc2-core-foundation differs from core-foundation
Just to get everyone up to speed, here's a quick overview of the differences.
The memory management strategy is as follows:
core-foundation |
objc2-core-foundation |
|---|---|
CFString |
CFRetained<CFString> |
&CFString |
&CFRetained<CFString> |
CFStringRef |
*mut CFString |
__CFString |
CFString |
| Not really possible | &CFString |
That is, objc2-core-foundation only has a single type that represents CFString, and memory management (CFRetain/CFRelease) is instead handled by a single generic wrapper type. This also meant that while I did initially consider building upon core-foundation instead of creating a new crate, it wasn't really an option in the end, as the internals are just too different.
objc2-core-foundation also avoids the *-sys split, instead preferring to expose everything in the same crate (again, to avoid a proliferation of types). A few of my guiding principles API-wise:
- Expose all internals such that users never need to write
extern "C" { ... }themselves. - Make everything as nice to use as possible when coming from Rust. Functions are exposed as associated functions/methods, conversions to/from common Rust types are provided.
- Be performance-minded when creating wrappers. For example, I wouldn't add a
CFURL -> Stringconversion, since that requires at least two CoreFoundation functions to be called. Instead,CFURL -> CFStringis provided, and so isCFString -> String.