Nathaniel Ford
Nathaniel Ford

Reputation: 21220

How do you use a parameter to a function that errors in the error handling code?

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

Playground

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

Answers (1)

matt
matt

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

Related Questions