我如何理解这个借来的值错误?构建Vec<& PathBuf>

时间:2015-09-27 19:21:00

标签: rust lifetime borrow-checker

我如何理解我违反的借阅检查器的哪一部分?

因为Rust的标准库walk_dirlisted as "unstable"(截至2015-09-27),我想我会尝试构建自己的函数来获取所有文件在一个目录及其自己的子目录中。

这是我在目录中列出文件所得到的,而不是查看子目录部分:

use std::fs::File;
use std::path::{Path,PathBuf};

fn get_files(this_path: &Path) -> Vec<&PathBuf>{
    let contents = fs::read_dir(this_path).unwrap();
    let mut output: Vec<&PathBuf> = Vec::new();

    for path in contents {
        let p = path.unwrap().path();
        if fs::metadata(&p).unwrap().is_dir() {
            // dunno, recursively append files to output 
        } else if fs::metadata(&p).unwrap().is_file() {
            output.push(&p)
        }
    }

    return output;
}

fn main() {
    for f in get_files(Path::new(".")) {
        println!("{}", f.display())
    }
}

当我尝试运行此代码时,出现此错误:

src/main.rs:58:26: 58:27 error: `p` does not live long enough
src/main.rs:58             output.push(&p)
                                        ^
note: in expansion of for loop expansion
src/main.rs:53:5: 60:6 note: expansion site
src/main.rs:49:48: 63:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 49:47...
src/main.rs:49 fn get_files(this_path: &Path) -> Vec<&PathBuf>{
src/main.rs:50     let contents = fs::read_dir(this_path).unwrap();
src/main.rs:51     let mut output: Vec<&PathBuf> = Vec::new();
src/main.rs:52
src/main.rs:53     for path in contents {
src/main.rs:54         let p = path.unwrap().path();
               ...
src/main.rs:54:38: 60:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 54:37
src/main.rs:54         let p = path.unwrap().path();
src/main.rs:55         if fs::metadata(&p).unwrap().is_dir() {
src/main.rs:56             // dunno, recursively append files to output
src/main.rs:57         } else if fs::metadata(&p).unwrap().is_file() {
src/main.rs:58             output.push(&p)
src/main.rs:59         }
               ...
error: aborting due to previous error

如果我错了,请纠正我,但我已经非常清楚地理解Rust的一个很酷的功能是你必须明确声明对象应该在函数范围之后生存。我认为我的问题是PathBuf中创建的let p = path.unwrap().path()在for循环的迭代结束时被丢弃,因此output Vec是提到已经消失的东西。

如果是这样的话:

当我做这样愚蠢的事情时,我如何建立更好的直觉?

是否有更好的惯用方法来从返回生命周期有限的资源的函数构建元素向量?

1 个答案:

答案 0 :(得分:3)

这里的直觉是:

  

我无法返回对函数内部创建的内容的引用,因为它将在该函数的末尾被释放,从而使引用无效。

相反,你必须把那个东西移出去。因此,Vec<PathBuf>拥有的Vec<&PathBuf>变体(因为PathBuf&PathBuf的拥有变体)应该是您的返回类型。