无法将foo作为不可变借用,因为它也被作为可变借用

7

我有以下(非常简单的)Rust代码:

let file = &Path(some_file_name);
let mut buf = [0u8, ..12];
match io::file_reader(file) {
    Ok(reader) => reader.read(buf, buf.len()),
    Err(msg) => println(msg)
}

rustc提示错误:

无法将buf[]作为不可变的借用,因为它也被作为可变的借用

如果将相应行更改为:

Ok(reader) => reader.read(buf, 12),

所有东西都能正常工作。但是,由于现在缓冲区的长度在代码中重复出现,因此这种方法不太令人满意。虽然我隐约知道为什么 rustc 抱怨,但我仍然想争论一下,认为 rustc 应该能够推断出 len() 是一个纯函数且没有副作用,因此代码是有效的。此外,按照那种方式读取缓冲区是相当常见的模式。

那么,在 Rust 中,什么是惯用的方式呢?

编辑:代码是针对 Rust 0.8 编写的。正如 @pnkfelix 指出的那样,Reader.read API 自那时起已经发生了变化。它不再需要第二个参数。


介意提供您的完整代码吗?我根据您的代码拼凑了一些东西,但我得到了不同的错误。您使用的是哪个版本的 Rust? - asm
顺便提一下,~PathPath 分配了一个盒子,而我们可以直接将 Path 放在栈上并取一个普通的引用,例如 &Path - huon
Andrew,这段代码是为 Rust 0.8 写的。Dbaupp,确实如此。&Path 会更好。 - edwardw
1个回答

8

这个答案是针对我的rustc版本:rustc0.9-pre(61443dc 2013-12-01)

  1. 当前版本的Reader trait接口与您列出的版本不同。它现在只需要(输出缓冲区的切片),而不是同时需要(输出缓冲区的切片和长度)。它可以从切片中获取输出缓冲区的长度,因此您不需要重复提供长度。

  2. Rust抱怨的原因是它试图确保您没有内存的读写别名。它试图阻止您将buf的不可变借用传递到一个上下文,并将buf的可变借用传递到另一个上下文。

    • 当您说len()是一个纯函数时,我理解为它不会写入任何可变状态。但是,在一般情况下,它可能会读取可变状态。(虽然在这里我们正在处理固定大小的缓冲区,但通常情况下,我们可能正在处理某些自动调整大小的数组抽象。)

    • 所以这里有一个效果,只是人们不经常考虑的:阅读。

    • 我怀疑应对您看到的问题的惯用方法(忽略API已更改的事实)是避免重叠借用buf,例如:

      Ok(reader) => { let l = buf.len(); reader.read(buf, l) },

这样,您就不会重复自己;您只需提供两个非重叠的范围,在不同的方式下借用了buf


这很有道理。谢谢,pnkfelix。 - edwardw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接