【问题标题】:cannot borrow foo as immutable because it is also borrowed as mutable不能借用 foo 作为不可变的,因为它也被借用为可变的
【发布时间】:2013-12-09 19:07:40
【问题描述】:

我有以下(足够无辜的)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?
  • 顺便说一句,~Path 正在为Path 分配一个框,此时可以将路径直接放在堆栈上并对其进行正常引用,例如&Path.
  • 安德鲁,代码用于 rust 0.8。 dbaupp,确实如此。 &Path 会更好。

标签: rust


【解决方案1】:

这个答案适用于我的 rustc 版本: rustc 0.9-pre (61443dc 2013-12-01)

  1. 当前版本的 Reader trait 的界面与您列出的不同。它现在只需要(一片)输出缓冲区,而不是同时获取(一片)输出缓冲区和长度。它可以从切片中获取输出缓冲区的长度,所以你不需要自己重复。

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

    • 当你说len() 是一个纯函数时,我认为你的意思是它不会写入任何可变状态。但是,在一般情况下,它可能是 reading 可变状态。 (这里不是这种情况,因为我们正在处理一个固定大小的缓冲区。但总的来说,我们可以想象我们正在处理一些自动调整大小的数组抽象。)

    • 所以有一种效果,只是人们不常想到的一种效果:阅读效果。

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

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

这样,您就不会重复自己;您只是提供了两个不重叠的范围,其中buf 以不同的方式借用。

【讨论】:

  • 这很有意义。谢谢,pnkfelix。
猜你喜欢
  • 1970-01-01
  • 2018-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多