Alex
Alex

Reputation: 7075

Possibly uninitialised variable from conditional

I'm writing a program that subsets an incoming file into either one or two output files depending on a CLI flag.

Minimally it works like so:

use std::{fs::File, io::Write};
fn main() {
    // Would be a CLI flag
    let write_all = true;

    let mut evens = File::create("evens.txt").expect("Nuh-uh");
    let mut odds: File;
    if write_all {
        odds = File::create("odds.txt").expect("Nuh-uh");
    }

    for i in 1..5 {
        if i % 2 == 0 {
            write!(&mut evens, "{}\n", i).expect("Can't write");
        } else {
            if write_all {
                write!(&mut odds, "{}\n", i).expect("Can't write");
            }
        }
    }
}

This won't compile due to odds being potentially uninitialised/out of scope as it's created in a conditional.

error[E0381]: borrow of possibly-uninitialized variable: `odds`
  --> src/main.rs:17:24
   |
17 |                 write!(&mut odds, "{}\n", i).expect("Can't write");
   |                        ^^^^^^^^^ use of possibly-uninitialized `odds`

error: aborting due to previous error

I've seen this answer about using Option<File>, but cannot see how to apply it to my problem.

Another alternative I've considered is just creating the odds.txt file and removing it at the end if !write_all is true, but I don't like this solution.

Upvotes: 0

Views: 512

Answers (1)

Alex
Alex

Reputation: 7075

Using Option<File> you need to set Some(File) or None. Then to use File you need to unwrap the &mut Option<File> to Option<&mut File>, which can be done using as_mut or by matching odds.

use std::{fs::File, io::Write};
fn main() {
    // Would be a CLI flag
    let write_all = true;

    let mut evens = File::create("evens.txt").expect("Nuh-uh");
    let mut odds: Option<File>;
    if write_all {
        odds = Some(File::create("odds.txt").expect("Nuh-uh"));
    } else {
        odds = None;
    }

    for i in 1..5 {
        if i % 2 == 0 {
            write!(&mut evens, "{}\n", i).expect("Can't write");
        } else {
            if write_all {
                // let mut file = odds.as_mut().unwrap();
                // write!(&mut file, "{}\n", i).expect("Can't write");
                match odds {
                    Some(ref mut file) => write!(file, "{}\n", i).expect("Can't write"),
                    None => panic!("No file?"),
                }
            }
        }
    }
}

Upvotes: 2

Related Questions