Small questions about using break

when i learn 《rust programming language》,i find an example about loop

code:

fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}

I run this program and found that when I remove the semicolon of the break statement, it can still run normally, but didn’t it mean that the statement would not return a value if I added a semicolon while reading the book?

Please format your code.


If you remove the semicolon from the loop, that's a problem.

But not if you remove it from the break. However, the if block doesn't end in a ; or have an else block, so you're intuition that it should be problematic makes some sense. Why isn't it?

An if without an else or an if ... { ... } else { ... } without a ; needs to have branches that evaluate to (). So this doesn't work, but this does -- even though the if branch "returns" a value of ().

So, does that mean break value evaluates to a ()? Almost, but not quite. Control flow like break value or return value evaluates to the never type, ! -- because the control flow never continues linearly after they execute. The never type can coerce into any other type -- including ().

That's what's going on here -- the break counter * 2 expression has type ! which is coerced to () so that the if { ... } is also of type (), as required.

Read more in the never type docs.

2 Likes

ok. thanks a lot

An if without an else or an if ... { ... } else { ... } without a ; needs to have branches that evaluate to () .

@nihaoqingtuan

Note that it can evaluate to something else if the if expression appears at the end of a function/block/closure. It then must evaluate to the same type as the enclosing function or block.

fn is_positive(x: i32) -> bool {
  if x >= 0 {
    true
  } else {
    false
  }
}
5 Likes