According to The Rust Reference,
If a
main
function is present, (snip), and its return type must be one of the following:
()
Result<(), E> where E: Error
but it doesn't say what happens when main()
returns ()
, Ok(())
or Err(<value>)
.
As far as I tested,
() |
Ok(()) |
Err(<value>) |
|
---|---|---|---|
Exit Status | 0 | 0 | 1 |
Additional Behavior | - | - | Error: <value> is printed to stderr |
Are these behaviors defined, explicitly explained or guaranteed in some documentation? In particular, can I assume
a program always exits with 1
status when main()
returns Err(<value>)
?
the error message displayed when main()
returns Err(<value>)
is always of the form Error: <value>
?
Notes:
I want some sort of documented guarantee rather than an empirical explanation. This is why I added #language-lawyer
tag.
This question is not about When should I use ()
and when should I use Result<(), E>
? or such. One can find answers (or at least hints or criteria) to such questions in many documentations or tutorials, as you know.
Updates:
Termination
trait is finally stabilized in Rust 1.61.0 (source).
The behavior of different return values from main
is defined by the std::process::Termination
trait:
trait std::process::Termination
A trait for implementing arbitrary return types in the main function.
This trait is documented to return libc::EXIT_SUCCESS
on success and libc::EXIT_FAILURE
on error.
The default implementations are returning
libc::EXIT_SUCCESS
to indicate a successful execution. In case of a failure,libc::EXIT_FAILURE
is returned.
But those values aren't guaranteed to be 0 and 1 on non-POSIX systems.
As for printing the error message, Termination
requires E: Debug
and does print the Debug
impl to stderr, but I don't believe it's guaranteed to stay exactly the same.
impl<E: fmt::Debug> Termination for Result<!, E> {
fn report(self) -> ExitCode {
let Err(err) = self;
eprintln!("Error: {:?}", err);
ExitCode::FAILURE.report()
}
}