我知道普遍的答案——你只能借用一次可变引用或多次不可变引用,但不能同时使用。我想知道为什么这种情况被认为是同时借用。
我有以下代码:
似乎在计算
我有以下代码:
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
let n = 3;
// checks on n and v.len() and whatever else...
let mut s = v[..n].to_vec();
for i in 0..n {
v[i + v.len() - n] = s[1];
}
}
在1.36.0版本下会产生以下错误:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:7:15
|
7 | v[i + v.len() - n] = s[1];
| ------^-----------
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
似乎在计算
x
之前没有办法对 v[x]
进行写入,这时不可变借用将完成。由于这里的顺序完全是串行的,为什么编译器不能识别依赖关系并将其视为非重叠借用?换句话说,是否存在任何情况会导致实际问题?
Marouane Fazouane 提出并发作为一种可能性,但我认为这不是问题所在。如果有另一个线程拥有(可能)可变引用,那么调用 v.len()
或开始 v[...]
将违反规定。这里,编译器知道所有发生在 v
上的操作——它是一个本地定义,没有其他调用。对我来说,问题在于为什么会出现同时借用,而在 len()
返回之前不可能发生 v[]
的情况。这类似于 v.mutable_call(v.immutable_call());
顺便提一下,编译器的早期版本(1.28)会给出一个错误,指示可变借用的结束括号,因此似乎顺序是基于源代码顺序的,由于源代码中两者交织在一起,因此它们可以被视为重叠。如果是这样,那么编译器肯定可以改进...对吧?
这似乎与为什么没有发生借用重叠时会出现借用错误?密切相关。
s[i] = v[i];
会在运行时出现错误,因为数组访问取决于向量的长度,而不是其容量。更好的表达方式是let s = v[..n].to_vec();
(当然,你需要确保n < v.len()以避免出错)。 - SCappella