使用移动的匹配变量的匹配语句抛出编译器错误

问题描述

我正在尝试遍历 Vec<String>文件路径并读取文件内容。但是,match 语句会引发有关模式中变量的编译器错误代码如下:

    //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",_ => {
                        println!("{}: UnkNown error",&path);
                        panic!("unkNown error opening file");
                    }
                }
                continue;
            }
        };
        
        /*get content from file variable*/
    }

这是我收到的编译器错误

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.

警告与此代码段中未包含的未使用变量有关。

我尝试借用 path_file 变量的内容,但收到相同的错误。我对这种情况的理解是,因为 path_file 块后面没有使用 path_resultfor,而且 path_result 在开始时重新绑定,所以即使是如果所有权超出 match 语句的范围。然而,情况似乎并非如此。

解决方法

你不能在 Rust 中使用未初始化的值。此代码不起作用:

// 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 {

上述代码也是您收到 value moved here,in previous iteration of the loop 错误的原因,因为您实际上并未在循环的每次迭代中初始化 path_result。重构代码以在每次迭代中无条件初始化 path_result 后,它就会编译:

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