Skip to content

rustc doesn't detect whether a loop happens once or more than once or never, in obvious cases #57555

Closed
@ghost

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

No one assigned

    Labels

    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions