Skip to content

Stabilize main with non-() return types #48453

@nikomatsakis

Description

@nikomatsakis
Contributor

This is a sub-issue of the larger tracking issue devoted to the ? in main RFC. It is specifically proposing that we stabilize the behavior that permits main to have a return type other than (). This return type must implement the Termination trait. The details of the trait itself (including its name and so forth) are not stabilized.

This commits us to the following (each link is to a test):

The changes from the RFC are as follows:

  • we modified the Result impl to use Debug

The following unresolved questions will be resolved:

  • The precise initial implementations
    • as above
  • exit codes (discussion)

But the following is not stabilized and free to change:

  • the name/location of the Termination trait and its methods
    • likely changing to std::process::Termination
  • the usage of -> Result<...> in unit tests (not yet landed)
  • the ErrCode newtype wrapper for returning a custom error code

--

UPDATE 1: Restricted the set of termination impls as proposed by @scottmcm in #48497.

Activity

nikomatsakis

nikomatsakis commented on Feb 23, 2018

@nikomatsakis
ContributorAuthor

@rfcbot fcp merge

I propose that we stabilize as described above.

rfcbot

rfcbot commented on Feb 23, 2018

@rfcbot
Collaborator

Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged teams:

Concerns:

Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

added
proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
on Feb 23, 2018
scottmcm

scottmcm commented on Feb 23, 2018

@scottmcm
Member

👍 to stabilizing the basics here.

👎 to some of the allowed return types.

I would propose only stabilizing the following new return types:

  • !
  • Result<(), E: Debug>
  • Result<!, E: Debug>

Thoughts on the others:

  • Arbitrary nesting is weird. Why would one have a Result<Result<!, io::Error>, fmt::Error>?
  • Nesting also makes return values weird, like with Result<i32, _> you run into collisions with Ok(1) and Err(_).
  • I still prefer some domain-specific type (strawman ExitCode) to i32. I could accept just fn main() -> i32, but it feels like primitive obsession (especially if nesting happens, where it's meaning is far less clear). There were some interesting discussions in the RFC about platform differences here too, which feel like they could be a good fit with the "vision for portability" stuff. And this case in particular isn't needed for the ?-in-main goals, so can easily wait. As a bonus, I think having a type here that's not a primitive would let us leave the impl but have have the type unstable as the details are figured out.

I'll happily make a PR restricting things as above if that'd be helpful.

cramertj

cramertj commented on Feb 23, 2018

@cramertj
Member

@rfcbot concern delay stabilization of nesting and i32 exit code

I feel basically the same way that @scottmcm does-- nesting (e.g. Result<i32, Error>) seems confusing and hard to reason about, and i32 seems like it should be ExitCode, perhaps with a from_raw method. Can we delay stabilizing these particular impls pending further discussion? I'd love to see ! and Result<!/(), E: Debug> stabilize.

Edit: also bool?

bkchr

bkchr commented on Feb 23, 2018

@bkchr
Contributor

Yeah it is the opposite, wasm is 0 and 1 and all other platforms use libc::*. I have done that, because libc::EXIT_SUCCESS and libc::EXIT_FAILURE were not available at that time for wasm in libc.

scottmcm

scottmcm commented on Feb 23, 2018

@scottmcm
Member

I noticed that there's impl Termination for bool right now too (it's not mentioned in the OP), which I don't think should be part of the minimal set that we stabilize in the first pass.

ExpHP

ExpHP commented on Feb 23, 2018

@ExpHP
Contributor

The RFC says E: Display instead of E: Debug, and tbh, Display would have been my first choice as well. But I'm sure this has been discussed.

Should the RFC be amended to reflect this change, and to explain why Debug is the right choice?

U007D

U007D commented on Feb 23, 2018

@U007D

@ExpHP yes, you are correct. Something approaching a summary of thinking around Display vs Debug starts around here: #43301 (comment).

withoutboats

withoutboats commented on Feb 23, 2018

@withoutboats
Contributor

I'm surprised by the concern about nesting - how would someone come to nest results in their main return anyway? It seems like the natural way to implement termination, which has the consequence of enabling this kind of thing, but that it happening in practice would be a non-issue.

Should RFC be amended to reflect this change, and to explain why Debug is the right choice?

we do not usually amend RFCs to cover changes before stabilization. they are design documents for implementation, they dont play any sort of 'constitutional' role.

U007D

U007D commented on Feb 23, 2018

@U007D

@withoutboats, that is interesting.

If I'm understanding you correctly, by allowing Result<T, E>, T itself may be a Result<U, F>, but that we should not invent extra machinery to disallow this? That does make a lot of sense...

Personally, I was only considering what to allow from the perspective of being conservative; but when being conservative mandates extra logic to specifically disallow certain types, I can see the problem. (Such a limitation could also feel quite arbitrary in blocking some scenario we might not be imagining at the moment...)

Thanks, as usual, for the enlightening perspective. :)

nikomatsakis

nikomatsakis commented on Feb 23, 2018

@nikomatsakis
ContributorAuthor

Fixed the wasm reference.

I also thought we might want to limit the impls. Note that we have no mechanism for "feature-gating" impls, so the only way to limit things once we stabilize the basic concept is to remove the stuff we don't want.

I think that supporting only the basics (!, (), and Result<(), E>) seems good to start -- I anticipate that anyone who wants to use this feature for more complex things will define their own new-type and implement Terminate themselves. That is certainly what I plan to do in my own code, since I think it's a nice way to separate out the error handling from the rest.

If we wanted to go crazy (I don't), I could imagine adding a new trait like SuccessfulTerminate and then implementing Terminate for T and Result<T, E> where T: SuccessfulTerminate. This avoids nesting but keeps flexibility. (We would implement SuccessfulTerminate for () and ExitCode or something.) But it feels like overkill, and it can be readily modeled with your own newtype anyhow.

32 remaining items

added 2 commits that reference this issue on Mar 23, 2018
dcf27e9
31462b8
added 2 commits that reference this issue on Mar 24, 2018
a64cd26
8d57071
added
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
on Apr 25, 2018
added
disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
and removed
final-comment-periodIn the final comment period and will be merged soon unless new substantive objections are raised.
on May 24, 2018
scottmcm

scottmcm commented on Sep 17, 2018

@scottmcm
Member

This stabilization happened; closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-enhancementCategory: An issue proposing an enhancement or a PR with one.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-langRelevant to the language teamdisposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jkordish@nikomatsakis@Centril@ExpHP@U007D

        Issue actions

          Stabilize `main` with non-() return types · Issue #48453 · rust-lang/rust