Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

rust - Match statement using moved matched variable throwing compiler error

I am attempting to iterate through a Vec<String> of file paths and read the content of the files. However, the match statement throws a compiler error regarding the variable in the pattern. The following is the code:

    //paths: Vec<String>
    //get counts in paths
    for path in paths.iter() {
        let mut path_result: Result<std::fs::File, std::io::Error>;
        let file: std::fs::File;

        if path != "-" {
            path_result = std::fs::File::open(&path);
        }

        //match result with error
        match path_result {
            Ok(path_file) => { file = path_file },
            Err(e) => {
                match e.kind() {
                    std::io::ErrorKind::NotFound => { println!("{}: No such file or directory", &path) },
                    std::io::ErrorKind::PermissionDenied => { println!("{}: Permission denied", &path) },
                    _ => {
                        println!("{}: Unknown error", &path);
                        panic!("unknown error opening file");
                    }
                }
                continue;
            }
        };
        
        /*get content from file variable*/
    }

This is the compiler error I receive:

error[E0382]: use of moved value
  --> src/main.rs:60:16
   |
51 |         let mut path_result: Result<std::fs::File, std::io::Error>;
   |             --------------- move occurs because `path_result` has type `std::result::Result<File, std::io::Error>`, which does not implement the `Copy` trait
...
60 |             Ok(path_file) => { file = path_file },
   |                ^^^^^^^^^ value used here after move
...
75 |     }
   |     -
   |     |
   |     value moved here, in previous iteration of loop
   |     value moved here, in previous iteration of loop

error: aborting due to previous error; 16 warnings emitted

For more information about this error, try `rustc --explain E0382`.
error: could not compile `test`

To learn more, run the command again with --verbose.

The warnings are in regards to unused variables not included in this snippet.

I have attempted borrowing the path_file variable's contents, but receive the same error. My understanding of the situation is that, because neither path_file nor path_result are used later in the for block and path_result is rebinded at the start, there should be no issue even if the ownership goes out of scope past the match statement. However, that seems to not be the case.

question from:https://stackoverflow.com/questions/65910494/match-statement-using-moved-matched-variable-throwing-compiler-error

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You cannot use uninitialized values in Rust. This code does not work:

// declare path_result here
let mut path_result: Result<std::fs::File, std::io::Error>;

// conditionally initialize it here
if path != "-" {
    path_result = std::fs::File::open(&path);
}

// potentially use uninitialized value: error!
match path_result {

The code above is also why you're getting the value moved here, in previous iteration of the loop error, because you're not actually initializing path_result in every iteration of the loop. Once you refactor the code to unconditionally initialize path_result in every iteration then it compiles:

fn example(paths: Vec<String>) {
    for path in paths.iter() {
        if path == "-" {
            println!("skipping un-openable path: -");
            continue;
        }

        let file = match std::fs::File::open(&path) {
            Ok(path_file) => path_file,
            Err(e) => {
                match e.kind() {
                    std::io::ErrorKind::NotFound => {
                        println!("{}: No such file or directory", &path)
                    }
                    std::io::ErrorKind::PermissionDenied => {
                        println!("{}: Permission denied", &path)
                    }
                    _ => {
                        println!("{}: Unknown error", &path);
                        panic!("unknown error opening file");
                    }
                }
                continue;
            }
        };

        /* get content from file variable */
    }
}

playground


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...