Rust only actually has a single loop, the other loops in Rust are just syntax sugar. Early in compilation the compiler will "de-sugar" a while or for loop into that ordinary infinite loop and so by the time your code is optimised it can't matter how you wrote the loop.
This answers the question Matt Godbolt had which caused him to create what would become Compiler Explorer, is a fancy modern for-each loop able to deliver the same perf as my 1970s loop? In Rust the answer is necessarily "Yes" because by the time the backend sees your program they're the same thing.
The reason Matt wanted to know is that obviously a for-each loop often has better ergonomics, so if they mean the same thing we should prefer our team to write this - but if they're slower that's a tough question, should we trade performance for clarity? The "Yes" answer that Matt found for C++ and which is baked into Rust means you don't need to make that trade decision, write whatever is easier to understand and maintain.
The reason for this is interesting. Loop constructs that you're guaranteed to enter have implications for control flow (in every language, not just Rust). It means that the following program is valid in Rust:
let x; // declared, but uninitialized variable
loop { // control flow is guaranteed to enter this loop
if some_condition() {
x = 42; // initialize x
break;
}
}
foo(x); // Rust knows that x is initialized as of here in all possible paths
In contrast, while loops check their condition before entering, which means the entire loop body might be skipped. Languages which guarantee initialization-before-use might special-case certain conditions for while loops as a hint to the control flow analysis (e.g. Java special-cases `while(true)`), but obviously this doesn't generalize to arbitrary conditions.
Interestingly, this all suggest that, in C-like languages, the more natural implementation of an infinite loop should not be `while(true)` nor `for(;;)`, but rather `do {} while(true)`, because do-while are also guaranteed to enter their body (and note that Rust doesn't feature do-while loops).
Rust only actually has a single loop, the other loops in Rust are just syntax sugar. Early in compilation the compiler will "de-sugar" a while or for loop into that ordinary infinite loop and so by the time your code is optimised it can't matter how you wrote the loop.
This answers the question Matt Godbolt had which caused him to create what would become Compiler Explorer, is a fancy modern for-each loop able to deliver the same perf as my 1970s loop? In Rust the answer is necessarily "Yes" because by the time the backend sees your program they're the same thing.
The reason Matt wanted to know is that obviously a for-each loop often has better ergonomics, so if they mean the same thing we should prefer our team to write this - but if they're slower that's a tough question, should we trade performance for clarity? The "Yes" answer that Matt found for C++ and which is baked into Rust means you don't need to make that trade decision, write whatever is easier to understand and maintain.
The reason for this is interesting. Loop constructs that you're guaranteed to enter have implications for control flow (in every language, not just Rust). It means that the following program is valid in Rust:
In contrast, while loops check their condition before entering, which means the entire loop body might be skipped. Languages which guarantee initialization-before-use might special-case certain conditions for while loops as a hint to the control flow analysis (e.g. Java special-cases `while(true)`), but obviously this doesn't generalize to arbitrary conditions.
Interestingly, this all suggest that, in C-like languages, the more natural implementation of an infinite loop should not be `while(true)` nor `for(;;)`, but rather `do {} while(true)`, because do-while are also guaranteed to enter their body (and note that Rust doesn't feature do-while loops).
Ooh, that's elegant, thanks for sharing