Skip to content

Reports "not all control paths return a value" when that's not true #1905

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

Closed
jsternberg opened this issue Feb 26, 2012 · 3 comments
Closed

Comments

@jsternberg
Copy link
Contributor

The following code fragment returns the following from the compiler:

fn get_input<T: copy>(default: T, f: fn(str) -> T) -> T {
    alt stdin().read_line() {
      "" { default }
      line { f(line) }
    }
}

fn yes_no_prompt(prompt: str, default: bool) -> bool {
    while true {
        print(prompt);
        let input = get_input(some(default)) {|x|
            alt str::to_lower(x) {
              "y" { some(true) }
              "n" { some(false) }
              _ { none }
            }
        };

        alt input {
          some(x) { ret x; }
          none { println("Invalid input"); }
        }
    };
}
hello.rs:52:53: 68:1 error: In function yes_no_prompt, not all control paths return a value
hello.rs:52 fn yes_no_prompt(prompt: str, default: bool) -> bool {
hello.rs:53     while true {
hello.rs:54         print(prompt);
hello.rs:55         let input = get_input(some(default)) {|x|
hello.rs:56             alt str::to_lower(x) {
hello.rs:57               "y" { some(true) }
            ...
hello.rs:52:48: 52:52 error: see declared return type of 'bool'
hello.rs:52 fn yes_no_prompt(prompt: str, default: bool) -> bool {
                                                            ^~~~

The control paths for this function should be fine. Putting "fail" at the end causes the compiler to work fine, but I haven't been able to find an input that causes it to fail.

@ghost ghost assigned catamorphism Feb 26, 2012
@catamorphism
Copy link
Contributor

This is a limitation of typestate -- the compiler doesn't know that the while loop in yes_no_prompt is infinite, because it doesn't treat the literal true specially. The path that doesn't return is the path where the loop condition (after some number of iterations, possibly 0) is false, and then you fall off the end of the function.

I have argued before (and I wasn't the only one) that this is a case for adding an infinite-loop construct so you could write forever { ... } instead of while(true) { ... } -- that way typestate would know that there is no way to exit the loop except through a break or return. The alternative would be to special-case knowledge about true as a loop condition into typestate, but I'm hesistant to add special cases since it seems like a slippery slope.

I'm going to close this issue, but open a new RFC for the infinite-loop construct.

@jsternberg
Copy link
Contributor Author

That works. I believe gcc has a similar problem with this construct, but I've seen C/C++ compilers that are able to handle this (which has caused problems when one compiler requires the return value, and one didn't). If you could post the RFC here after making it so I can keep track of it, that would be great.

@catamorphism
Copy link
Contributor

Yup, the RFC is #1906 -- I believe that some Java compilers also special-case true, but again, to me that just seems uglier than adding a forever construct to let you say what you mean.

Also, perhaps obvious, but the workaround for this (requiring no changes to the compiler) is to put either a fail, or a call to std::util::unreachable() (which also fails, that just makes the code a little clearer) after the loop body.

celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
…tions (rust-lang#2967)

This PR is the next step to rework/introduce the
`should_panic`/`fail_uncoverable` options as global conditions.

Until now, we haven't had a concrete proposal to do so other than the
implementation in rust-lang#2532. This PR presents one for each option in their
respective RFCs. I'd like to agree on this design before starting the
code review for rust-lang#2532.

Related to rust-lang#1905 rust-lang#2272 rust-lang#2299 rust-lang#2516
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants