[Solved] Why does panic! can be used in match arms as return unit type?

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.

1 Like

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.

1 Like

Thanks a lot for your replay !

panic has a return type of !, which means “doesn’t return.” You can substitute a value of ! for any other type, so this works.

As you’ve noted, println returns (), which does not have this property.

1 Like

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.

2 Likes