Can the compiler say when `break` has never been reached?

I have this code:

fn make_guess() -> u32 {
    loop {
        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .ok()
            .expect("Failed to read line");

        match guess.trim().parse() {
            Ok(num) => return num,
            Err(_) => {
                println!("Please input a number!");
                continue;
            }
        };
        break;
    }
}

When I run this code, the compiler complains:

expected `u32`,
  found `()`

Apparently, it break;returns a void value. However, it is impossible to achieve break;because of returnand continue.

Actually, if I delete break;, this works fine.

Is this a bug in the compiler or for some reason?

+4
source share
2 answers

A loopexpression that does not contain an expression breakis evaluated as !(i.e., it diverges), therefore it is compatible with all types.

fn main() {
    let _x: u32 = loop {}; // this compiles
}

, loop break (), ().

fn main() {
    let _x: u32 = loop { break; }; // mismatched types: expected `u32`,  found `()`
}

make_guess return loop. ! u32, () . ( return, , , ;.) break loop. , break .

@ker , loop break .

+4

, u32. - a Option<T> Some(T) None, , .

fn make_guess() -> Option<u32> {
    loop {
        let mut guess = String::new();
        io::stdin().read_line(&mut guess)
            .ok()
            .expect("Failed to read line");

        match guess.trim().parse() {
            Ok(num) => return Some(num),
            Err(_) => {
                println!("Please input a number!");
                continue;
            }
        };
        break;
    }
    None
}
+1

Source: https://habr.com/ru/post/1613908/


All Articles