Here is code in ch09 error Handling in The Rust Programming Language Book:
use std::fs::File;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => {
panic!("There was a problem opening the file: {:?}", error)
},
};
}
The return type of Err(error) arm is a unit type since a panic! macro, which should be unmatched with the return type of Ok(file) arm. It should not be compiled. But it is allowed!!! Why ???
If I change panic! macro to println! macro, it will not be compiled.
Read up on the never type, or !. panic! "returns" the never type. Essentially, the never type can not be instantiated. The never type captures the idea of "this function doesn't return".
The key bit is this:
This illustrates another behaviour of the ! type - expressions with type ! will coerce into any other type.
println!, of course, doesn't return the never type, so it can't be "converted" to a File like the never type can be.
Additional note: an expression statement (i.e., an expression followed by a semicolon ;) evaluates to ! (instead of ()) when the inner expression evaluates to !. This means that even if you add a semicolon after a panic! it will still typecheck.