在 Rust 中,如果 main 函数 returns Err 会发生什么?

In Rust, what happens if main function returns Err?

根据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

但它没有说明当 main() returns ()Ok(())Err(<value>).

时会发生什么

据我测试,

() Ok(()) Err(<value>)
Exit Status 0 0 1
Additional Behavior - - Error: <value> is printed to stderr

是否在某些文档中定义、明确解释或保证了这些行为?特别是,我可以假设


备注:


更新:

Termination trait 在 Rust 1.61.0 (source) 中终于稳定下来了。

来自 main 的不同 return 值的行为由 std::process::Termination 特征定义:

trait std::process::Termination

A trait for implementing arbitrary return types in the main function.

此特征记录到 return libc::EXIT_SUCCESS 成功和 libc::EXIT_FAILURE 错误。

The default implementations are returning libc::EXIT_SUCCESS to indicate a successful execution. In case of a failure, libc::EXIT_FAILURE is returned.

但是那些值 aren't guaranteed to be 0 and 1 on non-POSIX systems.


至于打印错误消息,Termination 需要 E: Debug 并将 Debug impl 打印到 stderr,但我不相信它能保证保持完全相同。

impl<E: fmt::Debug> Termination for Result<!, E> {
    fn report(self) -> ExitCode {
        let Err(err) = self;
        eprintln!("Error: {:?}", err);
        ExitCode::FAILURE.report()
    }
}

Source

此行为由 std::process::Termination Trait, which was added in RFC 1937 控制。特别是,调用 main() 的“隐藏”lang_start() 函数看起来大致像:

fn lang_start<T: Termination>(
    main: fn() -> T,
    argc: isize,
    argv: *const *const u8
) -> !

main()可以return任何T: Termination。在 std 中有 Terminationimplementations 对于 !()std::process:ExitCode 和一些 Result<T, E>-变体,其中 E: Debug。这就是为什么您可以 return ()Ok(()) 和其他 main().

关于你的问题,语言律师模式:任何依赖 Termination 的程序的确切行为都没有严格地由语言本身指定。它是 std 实现的一部分,而不是语言参考的一部分。这意味着同一个程序 可能 在使用不同版本的编译器编译时表现不同(绑定到不同的 std 版本)。 Err 情况下打印错误的确切行为是 documented 但未指定。由于 RFC 1937 明确寻找 POSIX-like 行为,您可以合理地确信该程序不会以令人惊讶的方式运行(例如,在 Err 情况下以状态 0 退出)。