Skip to content

Fix 'main' return value #289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tschwinge opened this issue Mar 17, 2021 · 7 comments
Open

Fix 'main' return value #289

tschwinge opened this issue Mar 17, 2021 · 7 comments

Comments

@tschwinge
Copy link
Member

As discussed in https://gcc-rust.zulipchat.com/#narrow/stream/281658-compiler-development/topic/Testsuite/near/230597886:

We're currently synthesizing a void main function (see -fdump-tree-gimple); this should (for now) probably be int main, plus the usual return 0 at the end.
(I'm aware of #144 "Implement main shim" which probably needs to be completed to resolve this properly.)

Fixing this (so that we get deterministic normal process termination) is a prerequisite for #281 "Create runnable test folder".

@github-actions
Copy link

Thanks for your contribution fellow Rustacean

@dkm
Copy link
Member

dkm commented Mar 17, 2021

In fact, it seems to follow what is being defined in the source:

fn main() -> i32  {
    1
}

Correctly returns 1 to the parent process.
It's not correct Rust, as rustc rejects this :

3 | fn main() -> i32  {
  |              ^^^ `main` can only return types that implement `Termination

But that can be used in the meantime to test execution behavior.

@dkm
Copy link
Member

dkm commented Mar 20, 2021

Is this really a valid issue? If we don't look at what Rust should really accept, declaring fn main() -> i32 works as expected (using return or the last expression returns the correct value).
Using void main has the same (wrong -- undefined) behavior as it has in C.

@philberty philberty added the bug label Mar 20, 2021
@philberty philberty added this to the Data Structures 3 - Traits milestone Mar 20, 2021
@philberty
Copy link
Member

This will be fixed as part of traits https://doc.rust-lang.org/std/process/trait.Termination.html

Though maybe we should consider implementing the never '!' type sooner than later. I thought this might be an unstable thing last I remember @flip1995 ?

@bjorn3
Copy link

bjorn3 commented Mar 20, 2021

Correct, the never type is still unstable. We want to stabilize it, but there are some back compat issues around type inference that could cause UB. The current plan is to add a lint for this I believe.

@bjorn3
Copy link

bjorn3 commented Mar 20, 2021

The Terminator trait is not necessary for fixing this issue. Only implementing the main shim is necessary. Rustc allows for #[lang ="start"] to take a main fn pointer returning () instead of any type implementing Terminator. So the following are both accepted:

#[lang = "start"]
fn lang_start(argc: usize, argv: *const *const u8, main: fn()) -> isize {
    main();
    0
}

fn main() {}

and

#[lang = "start"]
fn lang_start<T: Terminator>(argc: usize, argv: *const *const u8, main: fn() -> T) -> isize {
    main().report()
}

fn main() {}

(might have mixed up the argument order and used the wrong argv type)

@flip1995
Copy link
Member

So looking at the Rust reference for main function, exactly 2 types can be returned by main (in stable Rust):

  • ()
  • Result<(), E> where E: Error

When then looking at the Termination trait, it seems that a main function returning () gets lowered to just return ExitCode::SUCCESS = 0. So to fix this issue (for now), I think the only thing to do is lower a fn main() {} to int main() { return 0; }. To fix #144 more work is involved, I guess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants