Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

in loops, the error "borrow of possibly uninitialized variable" is overwritten by "borrow of moved value" in certain case(s) #57553

Closed
ghost opened this issue Jan 12, 2019 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ghost
Copy link

ghost commented Jan 12, 2019

In loops that are detected to happen more than once, the true error error[E0381]: borrow of possibly uninitialized variable: is overwritten by another error that doesn't seem to actually apply at all: error[E0382]: borrow of moved value:.

This happens possibly due to #52669 having been fixed.

Simple example (playground) follows, which is showing the fake error error[E0382]: borrow of moved value:; to see true error just uncomment the last break; line:

#![allow(unused_variables)]
#![allow(dead_code)]

struct NewType(i32);

fn main() {
    
    let mut v:Vec<NewType>=Vec::new();
    
    
    loop {
    //for i in 1..1 {
        //println!("iter{}",i);
        
        let a:NewType;
        //let mut a:NewType;
        //let a:NewType=NewType(3);
        //let mut a:NewType=NewType(3);//no errors with this line
        change(&mut a);//true but only happens without the "v.push(a)" below : "borrow of possibly uninitialized variable: `a`"
        v.push(a); //if this is uncommented then true error "borrow of possibly uninitialized variable: `a`" is overwritten by "borrow of moved value: `a`" and "value moved here, in previous iteration of loop"
       
        if 1==1 { //this breaks loop detection as happening only once(which a non-if break would do)
          break;
        }
        //break; //XXX uncomment this to see true error!
    }
}

fn change(i: &mut NewType) {
    *i=NewType(1);
}

Tested with rust nightly 2018, 11 Jan 2019 version, on playground.

Pedantic example on playground

@ibraheemdev
Copy link
Member

ibraheemdev commented Jan 2, 2021

I'm still getting the error on the playground with Rust 1.49:

fn blah() {
    loop {
        let blah: Option<String>; 
        if true {
            blah = Some("".to_string());
        }
        
        if let Some(blah) = blah.as_ref() {
            // ...
        }
    }
}
error[E0382]: borrow of moved value: `blah`
  --> src/lib.rs:8:29
   |
3  |         let blah: Option<String>;
   |             ---- move occurs because `blah` has type `Option<String>`, which does not implement the `Copy` trait
...
8  |         if let Some(blah) = blah.as_ref() {
   |                             ^^^^ value borrowed here after move
...
11 |     }
   |     - value moved here, in previous iteration of loop

@kadiwa4
Copy link
Contributor

kadiwa4 commented Jan 25, 2023

Fixed by #87998 and tested in tests/ui/moves/issue-72649-uninit-in-loop.rs.

@Noratrieb Noratrieb added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Apr 5, 2023
@estebank
Copy link
Contributor

Current output:

error[E0381]: used binding `a` isn't initialized
  --> src/main.rs:19:16
   |
15 |         let a:NewType;
   |             - binding declared here but left uninitialized
...
19 |         change(&mut a);//true but only happens without the "v.push(a)" below : "borrow of possibly uninitialized variable: `a`"
   |                ^^^^^^ `a` used here but it isn't initialized
   |
help: consider assigning a value
   |
15 |         let a:NewType = /* value */;
   |                       +++++++++++++
error[E0381]: used binding `blah` is possibly-uninitialized
 --> src/lib.rs:8:29
  |
3 |         let blah: Option<String>; 
  |             ---- binding declared here but left uninitialized
4 |         if true {
5 |             blah = Some("".to_string());
  |             ----
  |             |
  |             binding initialized here in some conditions
  |             binding initialized here in some conditions
...
8 |         if let Some(blah) = blah.as_ref() {
  |                             ^^^^ `blah` used here but it is possibly-uninitialized

We should remove the duplicated label, but other than that this is indeed fixed, likely by the PR linked above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants