Not a Rust expert, but I'll answer this from the perspective of a programmer and as a language designer.
Applications
Applications are in a special position: they know whether an error must be handled and how delicately.
Sometimes, applications can just quit on error. I wrote a command-line tool that just printed an error on malloc()
failure and exited. That was fine.
Sometimes, applications need to be super careful. I'm sure systemd
has to be careful while in the middle of bringing services up.
Libraries
Libraries know the same thing that applications do, but only for themselves. There may be other libraries and an application in the same process space.
So a library must handle its own errors properly, but it also must not remove the choice of the application.
IIRC, libgmp
, an arbitrary-precision number library, would quit on allocation failure, and that made application authors very sad because their application would suddenly quit without warning, and they couldn't do anything about it short of patching the library.
I have implemented a library myself, and this library does not just quit on allocation failure; it returns the failure.
Language Design
As we have seen above, libraries and applications have different concerns regarding error handling.
I believe this is why Rust has those two libraries.
But such error handling should not be built-in. That is a bad design.
Instead, the language should be designed in such a way that the error handling can be implemented as a library. This is hard because the language designer often can't anticipate how the community will want to handle errors, but I think the recent expressivity question and David Young's answer provide a great guideline because error handling is a global property of a program that we want to handle as locally as possible.
Essentially, a language that can do this is one that gives a lot of expressive power to libraries.
The fact that Rust has both implemented as libraries is a great testament to how well it was designed in this aspect.