在 Rust 中,如果 main 函数 returns Err 会发生什么?
In Rust, what happens if main function returns Err?
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
是否在某些文档中定义、明确解释或保证了这些行为?特别是,我可以假设
当 main()
returns Err(<value>)
?
时,程序总是以 1
状态退出
当 main()
returns Err(<value>)
始终为 Error: <value>
?
时显示的错误消息
备注:
我想要某种书面保证而不是经验解释。这就是我添加 #language-lawyer
标签的原因。
这个问题不是关于什么时候应该使用()
什么时候应该使用Result<(), E>
?之类的。如您所知,可以在许多文档或教程中找到此类问题的答案(或至少提示或标准)。
更新:
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()
}
}
此行为由 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
中有 Termination
的 implementations 对于 !
、()
、std::process:ExitCode
和一些 Result<T, E>
-变体,其中 E: Debug
。这就是为什么您可以 return ()
、Ok(())
和其他 main()
.
关于你的问题,语言律师模式:任何依赖 Termination
的程序的确切行为都没有严格地由语言本身指定。它是 std
实现的一部分,而不是语言参考的一部分。这意味着同一个程序 可能 在使用不同版本的编译器编译时表现不同(绑定到不同的 std
版本)。 Err
情况下打印错误的确切行为是 documented 但未指定。由于 RFC 1937 明确寻找 POSIX-like 行为,您可以合理地确信该程序不会以令人惊讶的方式运行(例如,在 Err
情况下以状态 0
退出)。
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 |
是否在某些文档中定义、明确解释或保证了这些行为?特别是,我可以假设
当
时,程序总是以main()
returnsErr(<value>)
?1
状态退出当
时显示的错误消息main()
returnsErr(<value>)
始终为Error: <value>
?
备注:
我想要某种书面保证而不是经验解释。这就是我添加
#language-lawyer
标签的原因。这个问题不是关于什么时候应该使用
()
什么时候应该使用Result<(), E>
?之类的。如您所知,可以在许多文档或教程中找到此类问题的答案(或至少提示或标准)。
更新:
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()
}
}
此行为由 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
中有 Termination
的 implementations 对于 !
、()
、std::process:ExitCode
和一些 Result<T, E>
-变体,其中 E: Debug
。这就是为什么您可以 return ()
、Ok(())
和其他 main()
.
关于你的问题,语言律师模式:任何依赖 Termination
的程序的确切行为都没有严格地由语言本身指定。它是 std
实现的一部分,而不是语言参考的一部分。这意味着同一个程序 可能 在使用不同版本的编译器编译时表现不同(绑定到不同的 std
版本)。 Err
情况下打印错误的确切行为是 documented 但未指定。由于 RFC 1937 明确寻找 POSIX-like 行为,您可以合理地确信该程序不会以令人惊讶的方式运行(例如,在 Err
情况下以状态 0
退出)。