Document the effect of main's return value?
https://github.com/rust-lang/reference/pull/1194#issuecomment-1101856264 suggests documenting how main()s return value affects the process's exit status.
I think the Reference doesn't currently have anything to say about what happens after main() returns.
I suggest adding a section in runtime.md saying roughly the following:
-
When (if)
main()returns, the runtime callsreport()on its result (which necessarily implementsTermination), which gives anExitCode. -
The runtime uses that
ExitCodein a platform-specific way to report information to the environment hosting the Rust program. -
Note: on Unix-like systems and Windows, the
ExitCodedetermines the process's exit status
Further, I think some part of Rust's documentation ought to be saying that, on Unix-like systems and Windows, ExitCode::SUCCESS leads to exit status 0, and ExitCode::FAILURE leads to exit status 1 (because we have to expect that users will rely on that behaviour). I think that part would be better in the standard library docs, but it isn't currently there.
I think it's important to say that report() is called, because that's what has the side-effect of printing a message to standard error (in the case where the returned value was a Result<_, Debug>).
So I think ideally the standard library docs would have entries for the specific Termination impls, saying how each of them behaves.
I think this approach would avoid the worry expressed in rust-lang/rust#93448: a no_std binary won't be using the Termination impls for Result<_, Debug>, because those are in std.
This sounds reasonable to me. The reference has historically not touched on platform-specifics like this, and has also somewhat ignored life before/after main as well. But I think making these statements about Termination seem like a good, small step.
@rust-lang/lang I would appreciate if someone could weigh in here. Are you OK with the reference specifying the exit-status behavior with respect to the Termination trait as discussed above?
Despite Termination being a library trait, it's used in the language "runtime" code that runs after main, so I think it should be documented in the reference.
And we should explicitly document how we pass through values.
Also, a bit more context from the lang team meeting. When we discussed this we agreed that we want the reference to include documentation about the runtime half of the return from main system. Such as specifying how it interacts with the Termination trait (calling report) and how it passes along the ExitCode, but that we should leave the documentation about the library APIs being consumed in the library API docs. Such as any indication of what report does for specific types or what values ExitCode::FAILURE/ExitCode::SUCCESS map to on specific platforms should live in the API docs, and the reference should only include a small section indicating that this additional information lives in the API docs with cross links to those docs.
RE. the above (w/ the context from reading the minutes of that aformentioned meeting after the fact), C requires that a status code 0 (and incidentally also EXIT_SUCCESS which may be the same or distinct) mean "successful" termination, though it doesn't require anything other than EXIT_FAILURE to mean "failed" termination.
RE. the above (w/ the context from reading the minutes of that aformentioned meeting after the fact), C requires that a status code
0(and incidentally alsoEXIT_SUCCESSwhich may be the same or distinct) mean "successful" termination, though it doesn't require anything other than EXIT_FAILURE to mean "failed" termination.
I don't think we'd necessarily want to copy C here, but we did discuss whether the u8 value an ExitCode is constructed from in rust should be distinct from the value it gets translated to for any specific platform. More concretely, the idea being that constructing an ExitCode from 0u8 will always give you ExitCode::SUCCESS, and any other value would always give you ExitCode::FAILURE or something equivalent, but ExitCode::SUCCESS doesn't necessarily need to map to 0 on any specific platform. The ultimate goal here is that we want to be as flexible as possible over what platform APIs we can abstract over, should , for example, some future rust based OS come along with a radically different interpretation of exit codes, we don't want to restrict their possible design space.
More concretely, the idea being that constructing an ExitCode from 0u8 will always give you ExitCode::SUCCESS, and any other value would always give you ExitCode::FAILURE, but ExitCode::SUCCESS doesn't necessarily need to map to 0 on any specific platform.
We should be able to construct arbitrary ExitCodes, though.
One of the reasons I believe for ExitCode (and indeed, one reason I need
it) is to return arbitrary status's to the environment, thus communicating
with w/e program may be waiting.
I'd expect ExitCode::new(20u8) to return 20 to the environment, not 1,
usually because I've prearranged the value "20" to have some special
meaning with something I know will be running the program (for example, for
cargo-native-install, a program that does an autotools-like install for
cargo projects, an exit status of 20 from a run target means
"Skipped.Target, Report, Continue Instalation", whereas 1 means "Fatal
install Error, Report, Abort Installation").
On Tue, 3 May 2022 at 14:43, Jane Lusby @.***> wrote:
RE. the above (w/ the context from reading the minutes of that aformentioned meeting after the fact), C requires that a status code 0 (and incidentally also EXIT_SUCCESS which may be the same or distinct) mean "successful" termination, though it doesn't require anything other than EXIT_FAILURE to mean "failed" termination.
I don't think we'd necessarily want to copy C here, but we did discuss whether the u8 value an ExitCode is constructed from in rust should be distinct from the value it gets translated to for any specific platform. More concretely, the idea being that constructing an ExitCode from 0u8 will always give you ExitCode::SUCCESS, and any other value would always give you ExitCode::FAILURE, but ExitCode::SUCCESS doesn't necessarily need to map to 0 on any specific platform.
— Reply to this email directly, view it on GitHub https://github.com/rust-lang/reference/issues/1196#issuecomment-1116440672, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABGLD232NFAUGND7H5VK4WTVIFXWLANCNFSM5T2CGF5A . You are receiving this because you commented.Message ID: @.***>
I think there's been some confusion here. I didn't mean to imply that ExitCode::from(20u8) would always map directly to ExitCode::FAILURE. I am just trying to make sure that cross platform assumptions around constructing ExitCodes hold up as best as possible when using the cross platform interface. I don't want people's code that assumes ExitCode::from(0) is always success to completely fail to work on platforms where they decided to have a different sentinel value represent success. In your example, the only time I expect ExitCode::from(20) would produce ExitCode::FAILURE is when you're running on a platform where ExitCode::SUCCESS == ExitCode(20), otherwise I'd just expect us to forward along the ExitCode(20) as intended.
Then, if we run into a situation where someone is running on a platform where ExitCode(0) represents a specific failure that they need to be able to represent we can add a platform specific API for constructing exit codes directly from that platform's expected representation, with docs detailing the exact ways the codes differ on that platform, and do so in a way that ensures that non-cross-platform code never compiles on other platforms.
We discussed this again in today's @rust-lang/lang meeting, and we want to confirm that we'd be happy to have the lang/runtime aspects of this documented in the reference. (The library semantics should remain in the library docs.)