Reputation: 21220
fn test() {
use std::path::PathBuf;
use std::fs::File;
let filename: PathBuf = PathBuf::from("hello");
let filename_clone = filename.clone();
match File::open(filename) {
Ok(_fp) => {
unimplemented!();
}
Err(_error) => {
println!("{}", filename_clone.display()); // Works
println!("{}", filename.display()); // Fails
}
}
}
Error:
error[E0382]: borrow of moved value: `filename`
--> src/lib.rs:13:28
|
5 | let filename: PathBuf = PathBuf::from("hello");
| -------- move occurs because `filename` has type `std::path::PathBuf`, which does not implement the `Copy` trait
6 | let filename_clone = filename.clone();
7 | match File::open(filename) {
| -------- value moved here
...
13 | println!("{}", filename.display()); // Fails
| ^^^^^^^^ value borrowed here after move
We understand that using filename
fails because File::open
has borrowed it and not yet released it. Yet, in the case where the open
fails (due to, say, the file not existing) we want to report on the actual input given to the open
. We can get around this by cloning the filename before we open it - but in that case we are essentially doubling the memory in the expectation but not the certainty that an error arises. This seems wrong-headed.
What is the correct way to handle this case? How do you bubble up information from the point of failure that makes for expressive and precise error handling? Or am I misunderstanding something about the mechanism here that would make it clear?
Upvotes: 0
Views: 298
Reputation: 79723
In the call File::open(filename)
, filename
hasn’t been borrowed, but rather moved and so you can’t use it later.
File::open
accepts any AsRef<Path>
, and so you can pass a reference to your PathBuf
(note the &
):
File::open(&filename)
Now it has been borrowed, and you can use it later in the error handling code.
Upvotes: 4