What is the different between a rust function "loop{}" returning "->!" and return nothing?

Viewed 67

I came across this function in rust:

#[no_mangle]
 pub extern "C" fn _start() -> ! {
    loop {}
}

From the answer here: What does "-> !" means in Rust I understood it never returns.

What is the difference between above function and the below without any return?

#[no_mangle]
 pub extern "C" fn _start() {
    loop {}
}

I'm able to compile both.

1 Answers

A Rust function with no explicit return type is equivalent to one whose return type is explicitly marked () (pronounced "unit"). This is the equivalent to void in the C++-family of languages. So

fn example() {
    loop {}
}

is equivalent to

fn example() -> () {
    loop {}
}

It effectively "ignores" the return value. So if we have a function bar() which returns i32, then

fn foo() -> i32 {
    bar()
}

is a function returning the result of bar, while

fn foo() {
    bar()
}

is a function which calls bar and then throws away its return value.

! (pronounced "never") is a bit special in Rust. A value of type ! can be assigned to a variable of any type. On the other hand, () is an ordinary type. So if we called the ! version of our example function in, say, one arm of a match statement, then it would happily coexist with whatever the return type of the match is.

match foo() {
    Some(x) => 0,
    None => example(),
}

example will agree with this match, since it will loop forever (or panic) and never return. But the () version of example will fail to compile, since () and i32 are not the same type.

In summary, if you can explicitly mark a function as returning !, then you should do so. A return type of ! is always better than one of (), since the former can be converted to the latter.

Related