joe
joe

Reputation: 5522

"borrow of possibly uninitialized variable" error in "obviously" unreachable block

In the following code example the compiler can work out that the if blocks aren't reachable, and yet it still gives me an error.

const A_MODE: bool = false; // I manually edit this to switch "modes"
fn main() {
    let a: Vec<u32>;
    if A_MODE {
        a = vec![1,2,3];
    }
    if A_MODE {
        println!("a: {:?}", a); // error: borrow of possibly uninitialized variable
    }
}

Rust Playground

I thought that maybe the compiler was really trying to tell me that I need to initialize a at some point, but this compiles fine:

fn main() {
    let a: Vec<u32>;
    println!("Finished.");
}

Is the error just because the Rust compiler isn't smart enough yet, or does this behaviour have some purpose? Is there any simple workaround which results in a similar code structure?

I know that I could restructure the code to make it work, but for my purposes the above structure is the most straight-forward and intuitive. My current work-around is to comment and uncomment code blocks, which isn't fun. Thanks!

Upvotes: 2

Views: 827

Answers (1)

SOFe
SOFe

Reputation: 8214

The compiler does not expand constant expressions in the phase for validating lifetime and ownership, so it is not "obvious" to the compiler.

If you really don't want to run that block, you might want to use #[cfg] (or the cfg-if crate if you like if syntax).

fn main() {
    let a: Vec<u32>;
    #[cfg(a-mode)] {
        a = vec![1,2,3];
    }
    #[cfg(a-mode)] {
        println!("a: {:?}", a); // error: borrow of possibly uninitialized variable
    }
}

This way, it will compile both usages without branching at all if a-mode cfg is set, and will not compile either of them otherwise.

The compiler is aware that constant expression conditions never change, but that is handled at a later phase of the compilation for optimizations like removing branching.

Upvotes: 4

Related Questions