【问题标题】:Match statement using moved matched variable throwing compiler error使用移动匹配变量的匹配语句引发编译器错误
【发布时间】:2021-01-26 22:59:01
【问题描述】:

我正在尝试遍历文件路径的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.

警告是关于未包含在此 sn-p 中的未使用变量。

我试图借用 path_file 变量的内容,但收到同样的错误。我对这种情况的理解是,因为path_filepath_result 都没有在for 块中使用,并且path_result 在开始时重新绑定,所以即使所有权超出范围也应该没有问题过去match 声明。然而,情况似乎并非如此。

【问题讨论】:

  • 错误信息很奇怪,path_resultinside循环中,所以它不能在之前的迭代中移动。我预计会出现 “使用可能未初始化的变量” 错误,例如 here without the loop
  • 看起来有一个issue already filed 来解决这个问题。

标签: rust pattern-matching match borrow-checker ownership


【解决方案1】:

你不能在 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-15
    • 2020-08-28
    • 2022-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多