stan0
stan0

Reputation: 11817

How does match compiles with `continue` in its arms?

I'm reading The Rust Programming Language book and I stumbled upon a simple expression:

let guess: u32 = match guess.trim().parse() {
    Ok(num) => num,
    Err(_) => continue,
};

How does match work with different kinds of expressions in its arms? E.g. the first arm would simply "return" num so that it's assigned to guess but in the second arm the expression is simply continue. How does match handle that and doesn't "assign" continue to guess but executes it? What happens with the whole assignment expression itself? Is it dropped from the call stack (if that's the correct term)?

Upvotes: 6

Views: 1948

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 71390

continue has a special type: it returns the never type, denoted !.

This type means "the code after that is unreachable". Since continue jumps to the next cycle of the loop, it'll never actually return any value (the same is true for return and break, and it's also the return type of panic!(), including all macros that panic: unreachable!(), todo!(), etc.).

The never type is special because it coerces (converts automatically) to any type (because if something cannot happen, we have no problems thinking about it as u32 or String or whatever - it will just not happen). This means it also unify with any other type, meaning the intersection of any type and ! is the other type.

match requires the expressions' type to unify (as does if). So your code returns the unification of ! and u32 == u32.

You can see that if you'll denote the type (requires nightly, since using the ! type not at return type position is experimental):

let num = match num {
    Ok(num) => {
        let num: i32 = num;
        num
    }
    Err(()) => {
        let never: ! = continue;
        never
    }
};

Playground.

Upvotes: 11

Related Questions