-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.

Description
I'm using issue #57553 to detect whether rustc
thinks that a loop happens once or more than once.
So far, I see only the following as being detected to happen once, which is true:
loop {
//some code here
break;
}
and I see the following incorrectly detected to happen more than once:
loop {
//code here
if 1==1 { break; } // loop happens once
}
for i in 1..1 { // loop happens never
//never-hit code here
}
for i in 1..=1 { // loop happens once
//code here
}
Proof that all of the above is true (playground link):
#![allow(unused_variables)]
//#![allow(dead_code)]
struct NewType(i32);
fn main() {
let mut v:Vec<NewType>=Vec::new();
loop {
println!("loop iteration");//hit once
let a:NewType;
change(&mut a); //true: "borrow of possibly uninitialized variable: `a`"
v.push(a);
break; // due to this break, the loop is detected as happening only once
}
loop {
println!("loop iteration");//hit once
let a:NewType;
change(&mut a); //false: "value borrowed here after move", see https://github.com/rust-lang/rust/issues/57553
v.push(a);// false: "value moved here, in previous iteration of loop"
if 1==1 { // loop is no longer detected as happening only once due to this 'if'
break;
}
}
for i in 1..1 {
println!("loop iteration");//never hit
let a:NewType;
change(&mut a); //false: "value borrowed here after move"
v.push(a);// false: "value moved here, in previous iteration of loop"
//break; //uncommenting this makes rust think the loop happens only once(even though it happens never) and thus reveals the true error: "borrow of possibly uninitialized variable: `a`"
}
for i in 1..=1 {
println!("loop iteration");//hit once
let a:NewType;
change(&mut a); //false: "value borrowed here after move"
v.push(a);// false: "value moved here, in previous iteration of loop"
}
for i in 1..=2 {
println!("loop iteration");//hit twice
let a:NewType;
change(&mut a); //false: "value borrowed here after move"
v.push(a);// false: "value moved here, in previous iteration of loop"
}
}
fn change(i: &mut NewType) {
//*i=NewType(1);
}
So, what else this means? dead code isn't detected in obvious cases like(playground):
#![warn(dead_code)]
fn main() {
for _ in 1..1 {
// loop happens never
println!("never"); //not detected as dead code
}
}
Metadata
Metadata
Assignees
Labels
A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)Area: Constant evaluation, covers all const contexts (static, const fn, ...)A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.Area: Lints (warnings about flaws in source code) such as unused_mut.