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

Match statement using moved matched variable throwing compiler error

我正在尝试遍历 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", &path) },
                    _ => {
                        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_filepath_result 都没有在 for 块中使用,并且 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