The Never Type and Unreachable Code Warnings

After reading through https://doc.rust-lang.org/book/ch19-04-advanced-types.html and coming across ! I decided to tinker around with it.

fn bar() -> ! {
   loop {}
}

It makes sense to me that this compiles and without warning. The function never returns so the return type can never have a value.

fn bar() -> i64 {
   loop {}
   1
}

With this, I get an unreachable expression warning. I guess I understand that the return type is allowed because, if the expression were to be reached, it would match the return type.

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

This is the same as the first code block except for the return type, and compiles the same, without warning. Here, I'm confused. The compiler agrees with the return type of ! and (). To me, this example is similar to the i64 example in that () could be returned if it were reached.

Is the lack of a warning here an inaccuracy by the compiler?

You can convert a value of type ! into any other type, including () or i64, so your third bar simply has an implicit conversion from ! to ().

3 Likes

Oh! Thank you!

I didn't try:

fn bar() -> i64 {
    loop {}
}

This makes more sense to me now. I guess I could have come to that conclusion from the book examples with the match arms.

1 Like

I think the logic is that if a function never returns, the return type could be anything. That's why ! can be coerced to anything.

With the never_type feature you can even create an expression with type ! and coerce it to something else. That's effectively what your fn bar() -> i64 { loop {} } example is doing.

#![feature(never_type)]

fn do_something(x: !) {
    let y: i64 = x;
    let s: String = x;
    let reference: &mut Vec<f64> = x;
}

(playground)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.