So I have a rust code that acts as a CLI, it has a -o filename.txt kind of optional syntax which if given makes the program write some contents to a file, if not given it skips the file writing part.
A simple code without any of the complicated variable comes down to this:
fn main() {
let x:i64; // define the file
let y = true; // if -o is present, false otherwise (it'll be mut)
if y {
x = 1; // open file in argument of -o
}
// some other logics and actions, it won't change y.
if y {
println!("{}", x); // write to file
}
}
So basically the value of x will be initialized and accessed only when y is true, so it'll never be accessed uninitialized. But rust throws this error:
error[E0381]: borrow of possibly-uninitialized variable: `x`
--> src/main.rs:11:21
|
11 | println!("{}", x); // write to file
| ^ use of possibly-uninitialized `x`
So there is similar problem solved in this: question
But unlike that question i need y be a variable so the if statement needs to be checked in runtime instead of compile time. Is there a way to compile it by telling the compiler it's ok?
Actual code is here (to avoid asking the wrong question as the solution could be to use a different method instead of forcing the compiler):
[dependencies]
clap={ version = "3.0", features = ["derive"] }
use std::{io, thread, time};
use std::io::Write; // for flush
use std::fs;
use clap::Parser;
#[derive(Parser)]
struct Cli {
/// Do not clear output file before writing to it
#[clap(short, long, action)]
append: bool,
/// Output File to write the captured contents.
#[clap(parse(from_os_str), short, long, default_value = "")]
output: std::path::PathBuf,
}
fn main() {
let args = Cli::parse();
let mut out_to_file = false;
if !args.output.as_os_str().is_empty() {
out_to_file = true;
}
let mut file;
if out_to_file {
file = fs::OpenOptions::new()
.write(true)
.create(true)
.append(args.append)
.truncate(!args.append)
.open(args.output)
.unwrap();
}
let clip_new = "Test String";
let separator = "\n";
loop {
print!("{}{}", clip_new, separator);
io::stdout().flush().unwrap();
if out_to_file{
file.write_all(clip_new.as_bytes()).expect("Unable to write to file.");
file.write_all(separator.as_bytes()).expect("Unable to write to file.");
}
thread::sleep(time::Duration::from_millis(1000));
}
}
So the current workaround I have is to have file always initialized.
My current workaround opens a temp file, and uses it to write the output if user does want a output file. But I'd prefer to not open a file if user doesn't want it.
let mut out_file = env::temp_dir().join("testfile.txt");
if !args.output.as_os_str().is_empty() {
out_file = args.output;
}
Using this and opening out_file instead of args.output without any conditional checks (removing all if out_to_file).