Introduction
Hey, I've been thinking about how to make Objective-C's and Rust's memory models play nicer together.
Objective-C has two different "states" for references: Retained and autoreleased. In Rust there's the concept of ownership, which means we're the only place that holds a reference to that object - this is how we get safe mutability.
As such, in Rust, an Objective-C reference can be in a multitude of different "states":
- Retained and owned
- Retained and aliased
- Autoreleased and owned
- Autoreleased and aliased
In Rust we also have the borrow checker, so we can furthermore safely copy and return references without needing to retain and autorelease them first (provided they do not outlive the Objective-C reference).
The idea
I would like to propose an addition to objc that makes it possible to handle these references safely and ergonomically for users of the library. The idea is to add two smart pointers, Owned and Retained (names are up for bikeshedding), and modify the autoreleasepool function to carry some lifetime information (this would be the only breaking change, and could easily be ignored for people who don't want it).
See the following code snippets for a better explanation:
Library authors would then be able to create functions like MyObject::new that would return an Owned<MyObject> and MyObject::get_from_somewhere that would take a &'p AutoreleasePool parameter, and return &'p MyObject.
For some of these things to be sound we'll need some nightly features or debug assertions (probably nightly features under a feature flag, debug assertions if not), but I think it's doable.
Outro
I'll be brewing a few PRs in the coming days, but would you, @SSheldon, welcome this addition? (Of course, it'll need modifications)
As a real-world usecase, I know there are several minor memory leaks in the MacOS backend of winit, but I haven't bothered to fix them because I know they will appear again after a refactor. If objc had some better mechanism for keeping track of references, like the one described in this issue (or if someone has a better idea), we would be able to eliminate most of these issues.
Introduction
Hey, I've been thinking about how to make Objective-C's and Rust's memory models play nicer together.
Objective-C has two different "states" for references: Retained and autoreleased. In Rust there's the concept of ownership, which means we're the only place that holds a reference to that object - this is how we get safe mutability.
As such, in Rust, an Objective-C reference can be in a multitude of different "states":
In Rust we also have the borrow checker, so we can furthermore safely copy and return references without needing to retain and autorelease them first (provided they do not outlive the Objective-C reference).
The idea
I would like to propose an addition to
objcthat makes it possible to handle these references safely and ergonomically for users of the library. The idea is to add two smart pointers,OwnedandRetained(names are up for bikeshedding), and modify theautoreleasepoolfunction to carry some lifetime information (this would be the only breaking change, and could easily be ignored for people who don't want it).See the following code snippets for a better explanation:
Retained and owned:
Retained and aliased:
Autoreleased and owned:
Autoreleased and aliased:
Library authors would then be able to create functions like
MyObject::newthat would return anOwned<MyObject>andMyObject::get_from_somewherethat would take a&'p AutoreleasePoolparameter, and return&'p MyObject.For some of these things to be sound we'll need some nightly features or debug assertions (probably nightly features under a feature flag, debug assertions if not), but I think it's doable.
Outro
I'll be brewing a few PRs in the coming days, but would you, @SSheldon, welcome this addition? (Of course, it'll need modifications)
As a real-world usecase, I know there are several minor memory leaks in the MacOS backend of
winit, but I haven't bothered to fix them because I know they will appear again after a refactor. Ifobjchad some better mechanism for keeping track of references, like the one described in this issue (or if someone has a better idea), we would be able to eliminate most of these issues.