> and mostly a consequence of eschewing exceptions.
A panic is the same thing as an exception. If you want to catch a panic, use recover(), it's meant to be used exactly for these end-of-the-world panic scenarios (and for FFI/etc).
You can plug in a custom allocator that panics on OOM (I think the standard one aborts).
As Steve mentioned, custom allocators can mean two things. The type that exists in rust today is one where you can make OOM panic, but not have allocation methods return Result. A planned extension will let you have allocators with different semantics entirely work with stdlib types (via defaulted type parameters); and this will let you use regular error handling with stdlib types too.
> A planned extension will let you have allocators with different semantics entirely work with stdlib types
And what about all the code that doesn't? It's because so much code exists that's completely oblivious to the possibility of these stdlib functions failing that I don't think that merely adding the option to do the right thing is good enough. The existing failure-oblivious APIs need to be explicitly deprecated.
The only ways to redeem Rust is to either support exceptions as first-class citizens with mandatory runtime support or to convert all existing allocating stdlib functions to return Result and mark all the existing failure-oblivious ones as being as deprecated as gets(3) in C.
> The existing failure-oblivious APIs need to be explicitly deprecated.
That's total overkill. For 99% of applications, process abort is fine, and dealing with it is just noise. Those 1% are usually things like kernels that use custom standard libraries anyway.
We're not doing the 99% a favor by making them think about OOM every time they do something that might allocate.
> The only ways to redeem Rust is to either support exceptions as first-class citizens with mandatory runtime support or to convert all existing allocating stdlib functions to return Result and mark all the existing failure-oblivious ones as being as deprecated as gets(3) in C.
This is silly hyperbole. Ask anyone who works in security whether the danger of xmalloc() is comparable to the danger of gets(). In fact, I've seen many security folks recommend only using xmalloc() with process abort instead of trying to explicitly handle OOM failures!
> Yes it does. That some compilers provide a way to disable mandatory language features is no argument.
It's actually very relevant that huge amounts of C++ deployed in the world use -fno-exceptions, and many shops (for example, Google!) have a policy of "we do not use exceptions". I don't care about how well languages handle OOM in theory; what matters is how well they handle it in practice.
Google's C++ coding standards have done tremendous harm to the C++ community by perpetuating obsolete programming practices like two-phase initialization and lossy error reporting. Google's C++ standards also teach people that it's okay to use the STL and not worry about allocation failure, which hurts program robustness generally.
I think it's hard to argue that Google is in the wrong by not wanting to rely on std::bad_alloc for dealing with OOM.
> Google's C++ standards also teach people that it's okay to use the STL and not worry about allocation failure, which hurts program robustness generally.
Actually, I think making std::bad_alloc call std::terminate improves program robustness by a lot over trying to gracefully recover from all allocation failure. Certainly it reduces security vulnerabilities.
Are you saying C++ make it easy to write exception-safe code? Because Rust explicitly encodes exception safety into the type system with the RecoverySafe trait, you need to write unsafe code to bypass that, and the documentation on unsafe explicitly covers exception safety.
Rust doesn't consider exception safety to be a matter worth 'unsafe's time. All code must simply be memory-safe in the face of unwinding. RecoverySafe is basically "it's hard to leak busted state out of a region of code that panicked". That is, mutable references aren't RecoverySafe, and mutexes and the like poison their contents if they witness a panic while locked.
But RecoverySafe is just preventing things like "your binary heap was only partially heapified" and not "your heap is now full of uninitialized memory". You can get poisoned values out of mutexes just fine, so everything needs to put itself in a memory-safe state if a panic occurs.
One can bypass RecoverySafe in safe code with the AssertRecoverySafe wrapper.
It does however turn out that safe code in Rust is generally quite exception-safe by default. This is because safe code can't do anything too dangerous, panics are generally only caught at thread or application boundaries (so data that witnesses a panic is usually well-isolated) and there's way less places that can unwind compared to "override everything" C++. But exception safety is indeed something unsafe code needs to fight for (see the aforementioned binary heap in std).
It doesn't guarantee destructors will run, that's true, but that's for things like Rc cycles. Take a look at the RFC for std::panic::recover- it definitely takes exception safety into account: https://github.com/rust-lang/rfcs/blob/master/text/1236-stab...
Also take a look at things like the design of the Drain iterator- the stdlib is definitely (intended to be) exception safe.
A panic is the same thing as an exception. If you want to catch a panic, use recover(), it's meant to be used exactly for these end-of-the-world panic scenarios (and for FFI/etc).
You can plug in a custom allocator that panics on OOM (I think the standard one aborts).
As Steve mentioned, custom allocators can mean two things. The type that exists in rust today is one where you can make OOM panic, but not have allocation methods return Result. A planned extension will let you have allocators with different semantics entirely work with stdlib types (via defaulted type parameters); and this will let you use regular error handling with stdlib types too.