Excerpt from Chapter 3.5 of the Rust Book:
we use the
break
keyword with the valuecounter * 2
. After the loop, we use a semicolon to end the statement that assigns the value toresult
.
Plus the code snippet:
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {}", result);
}
I understand how this works and why the result is 20, but I noticed that if I remove the semicolon on the line that contains the break
keyword, the program is equivalent.
Why is the semicolon optional in this case?
A shorter example:
let _: i32 = loop {
if true {
break 3; // ()
}
};
That is just another example where the semi-colon does not interfere with the intended outcome. For one, the insertion of a semi-colon introduces an expression statement, which evaluates to the unit type ()
. As the loop
s and if
expressions continue to admit a code block evaluating to the same type ()
, then all types are in conformance.
let _: i32 = loop {
if true {
break 3 // ! coerced to ()
}
};
If the semi-colon is taken away, the break
is evaluated to the never type !
, which coerces to any other type. This means that it will fulfill any type expected by the outer scope. In this case, break 3
alone also becomes ()
to fulfill the if expression. So all is well all the same, so long as you don't try to append any other statement before the end of the if block.
Both break
and return
evaluate to !
, as their side effects imply that the program will not go through with the natural workflow.
See also: