不能借用foo作为不可变因为它也被借用为可变的

时间:2013-12-09 19:07:40

标签: rust

我有以下(无辜)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从那时起就已经改变了。它不再需要第二个参数。

1 个答案:

答案 0 :(得分:7)

这个答案适用于我的rustc版本: rustc 0.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

  3. 这样,你不要重复自己;你只是提供两个不重叠的范围,其中{{1}}以不同的方式借用。