Function calling other that exits, and branch type mismatch

fn exit_with_error(error: &str) {
    writeln!(&mut stderr(), "ERROR: {}", error).unwrap();
    process::exit(1);
}

How to use the above in function like this:

fn func(x: bool) -> Vec<String> {
    if x {
        vec!["a".to_string(), "b".to_string()]
    } else {
        exit_with_error("oh no!")
    }
}

Here a playground example. Rust Playground

I can make it work, explicitly calling process::exit(1); below each exit_with_error call, but maybe there's better way? :confused: Or maybe I'm just totally missing something, and an early exit is just plain wrong?

1 Like
3 Likes

Just to clarify what @blackbeam said (because it's a link-only answer). Rust doesn't say that exit_with_error function never returns - in fact it says that it returns () (no value).

To handle functions that will never ever return, Rust does provide a type that is impossible to get an instance of, it's called ! (just an exclamation mark). Saying fn exit_with_error(error: &str) -> ! { essentially says that the function can never return. There are functions in Rust with such a type signature, like this.

pub fn exit(code: i32) -> !

Because your function does inevitably call process:exit, which does return !, Rust knows that this function can possibly never return (which is why () return type is allowed, as function that never returns in theory can return anything, as user will never see it).

This needs to intentionally specified, as otherwise changing the function to actually return would break the code.

5 Likes

... and the official name for these types of functions is "diverging functions".

1 Like

It was i'm-late-for-the-train answer)

@blackbeam Your link was enough to get me to read more about it and solve my problem. Thank you :slight_smile:

@xfix Thank you for verbose answer. It's what I found when searching web after @blackbeam answer, but it's really nice to have it in the thread. With your answer one does not have to look for what does ! really do :slight_smile:

Stictly speaking () is a type with exactly one value, which is also called ().
So a function that returns () will actually return a value, but since it can only return the same one value, that value carries no information (i.e. can be of size 0).

1 Like