rust - 如何解决传递给闭包的 &PathBuf 冲突的生命周期要求?

标签 rust

我有一个 PathBuf需要传递给闭包来解析路径,我添加了一些生命周期来解决 rustc 提示的其他问题,但现在我收到以下错误:cannot infer an appropriate lifetime for borrow expression due to conflicting requirement .我不确定如何解决它或在哪里可以找到文档以了解如何解决它。

fn read_tag_file<'a>(
    path: &'a PathBuf,
    cwd: &'a PathBuf,
    winwidth: usize,
    files: &'a Vec<PathBuf>,
) -> Result<impl Iterator<Item = String> + 'a> {
    let file = File::open(path).unwrap();

    Ok(BufReader::new(file).lines().filter_map(move |line| {
        line.ok().and_then(|input| {
            if let Ok(tag) = TagInfo::parse(&path, &input) {
                Some(tag.format(&cwd, winwidth))
            } else {
                None
            }
        })
    }))
}


fn read_tag_files<'a>(
    cwd: &'a PathBuf,
    width: usize,
    files: &'a Vec<PathBuf>,
) -> Result<impl Iterator<Item = String> + 'a> {

    let cwd = cwd.clone();

    let streams = files
        .clone()
        .into_iter()
        .map(move |path| read_tag_file(&path, &cwd, width, files))
        //                                    ^^^^ conflict here :/
        .flatten();

    let stream = Box::new(std::iter::empty()) as Box<dyn Iterator<Item = String>>;
    let stream = streams.fold(
        stream,
        |acc, f| Box::new(acc.chain(f)) as Box<dyn Iterator<Item = String>>
    );

    Ok(stream)
}
作为引用,这里是完整的错误输出:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
   --> crates/maple_cli/src/cmd/tagfiles.rs:135:47
    |
135 |         .map(move |path| read_tag_file(&path, &cwd, winwidth, files))
    |                                               ^^^^
    |
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 135:14...
   --> crates/maple_cli/src/cmd/tagfiles.rs:135:14
    |
135 |         .map(move |path| read_tag_file(&path, &cwd, winwidth, files))
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `cwd`
   --> crates/maple_cli/src/cmd/tagfiles.rs:135:47
    |
135 |         .map(move |path| read_tag_file(&path, &cwd, winwidth, files))
    |                                               ^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 125:19...
   --> crates/maple_cli/src/cmd/tagfiles.rs:125:19
    |
125 | fn read_tag_files<'a>(
    |                   ^^
note: ...so that return value is valid for the call
   --> crates/maple_cli/src/cmd/tagfiles.rs:129:13
    |
129 | ) -> Result<impl Iterator<Item = String> + 'a> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

最佳答案

没有 read_tag_file (或至少它的签名)真正诊断问题有点困难。
我认为问题是read_tag_file以某种方式混淆 path 的生命周期, filescwd (可能函数使用生命周期省略或者所有三个都绑定(bind)到相同的生命周期?),这意味着 Rust 假设 &cwd必须对 'a 有效, 它不可能是因为 cwd只有在闭包还存在的情况下才会存在。
编辑:添加新功能后,我可以更好地看到依赖关系,问题是你复制的太多或不够:你可以通过复制更多来绕过这个问题,但以效率为代价,但这里你的代码是非常接近,您还有两个问题,至少要编译(不确定调用者是否会满意):

  • 你正在克隆 cwd在函数内部,这意味着 cwd你在闭包中移动只为函数而存在,但闭包本身需要比函数生命周期更长,你根本不能克隆 cwd,它已经是 &PathBuf这正是你想要的
  • 然后 files.clone()单独克隆路径,这意味着您的 &path仅在闭包内有效,但闭包的输出是借用的(尽管我认为不需要),但无论如何这里又是完全没有必要的,files&[PathBuf] ,您可以按原样使用它

  • fn read_tag_files<'a>(
        cwd: &'a PathBuf,
        width: usize,
        files: &'a Vec<PathBuf>,
    ) -> Result<impl Iterator<Item = String> + 'a> {
        let streams = files
            // don't copy the files
            .into_iter()
            .map(move |path| read_tag_file(&path, cwd, width, files))
            //                                    just use the cwd you have, it's fine as-is
            .flatten();
    
        let stream = Box::new(std::iter::empty()) as Box<dyn Iterator<Item = String>>;
        let stream = streams.fold(
            stream,
            |acc, f| Box::new(acc.chain(f)) as Box<dyn Iterator<Item = String>>
        );
    
        Ok(stream)
    }
    

    关于rust - 如何解决传递给闭包的 &PathBuf 冲突的生命周期要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64475813/

    相关文章:

    rust - rust-chrono 中的 ParseError(NotEnough) 是什么意思?

    rust - 从Vec移除一系列元素

    rust - 读取和写入长时间运行的 std::process::Child

    rust - 特征签名中 `Self` 的生命周期参数

    rust - 为什么 Vec::resize 是一个不稳定的函数?

    rust - 具有 Sized 超特征的特征仍然有错误 "std::marker::Sized is not satisfied"

    linux - 为什么 999µs 太短而 1000µs 恰到好处?

    rust - One::one() 与 1 有什么区别

    rust - 将迭代器或集合传递给函数

    rust - 为什么我不能在方法中混合返回和表达式