I guess if any language can help you build a stable classic-Mac app it’ll be Rust. How does Rust handle failable allocations? In my brief usage of it I don’t remember having to deal with failure cases for every heap allocation, but I may just be forgetting.
(I don’t know if you plan to go further with this, but classic Mac apps that did a lot of traditional (non-Handle) allocation tended to include their own allocator implementations that reserved large chunks from temp-mem. Doing a lot of NewPtr in the app heap led to excessive fragmentation and premature failures.)
Rust itself doesn’t allocate by default, if you use it without the standard library there isn’t an allocator in the first place unless you create one.
The “normal” methods in the standard library that allocate handle allocation errors by crashing. There’s been some work on adding alternate methods that return errors that you can use instead, but you are giving up some ergonomics. You could of course implement your own container classes and so on that always bubble up allocation errors to the caller, either from scratch, or by wrapping the standard classes and only using the methods that bubble up errors.
oom=panic is slowly getting there (AFAIK the code around allocators can handle unwinding now, there’s just an issue of panic using Box).
try_reserve already goes a long way, since likelihood of OOM is proportional to allocation size, and Vecs and HashMaps tend to be the large ones. This is especially true on old systems that suffer from memory fragmentation.