考虑这个代码(Rust Playground):
#[derive(Clone, Copy, Debug)]
struct X(i32);
impl std::ops::AddAssign for X {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
fn main() {
let mut ary_i32 = [1_i32; 2];
ary_i32[0] += ary_i32[1]; // OK
let mut ary_x = [X(1); 2];
ary_x[0] += ary_x[1]; // OK
let mut vec_i32 = vec![1_i32; 2];
vec_i32[0] += vec_i32[1]; // OK
let mut vec_x = vec![X(1); 2];
vec_x[0] += vec_x[1]; // error[E0502]: cannot borrow `vec_x` as immutable because it is also borrowed as mutable
}
Run Code Online (Sandbox Code Playgroud)
为什么我只vec_x在线获得 E0502 ?我不明白为什么只允许ary_x和的操作vec_i32。借用检查器是否特别对待内置类型 ( i32, array)?
我研究了一些资源并阅读了我的代码的 MIR,并设法了解发生了什么。@trentcl
的评论将是最好的答案。我尽量写详细。
对于array,Index和IndexMuttrait 没有使用,编译器直接操作数组元素(你可以用 MIR 看到这一点)。所以,这里不存在借贷问题。
Explanating的Vec,rustc指导是非常有用的。
首先,两阶段借用不适用于vec_foo[0] += vec_foo[1]语句。
而且,之间的区别i32,并X是造成运营商降低。
基本上,语句 likevec_user_defined[0] += vec_user_defined[1]转换为函数调用add_assign(index_mut(...), *index(...)),函数参数从左到右求值。因此,index_mut()借用x性情不定地并index()试图借x,和失败。
但是对于像 那样的内置类型i32,复合赋值运算符不会转换为函数调用,并且 rhs 在 lhs 之前被评估(你可以看到index()在index_mut()MIR之前被调用)。所以,对于内置类型,vec_builtin[0] += vec_builtin[1] 作品。
我从lo48576 的文章(日文)中知道这些事情。
我考虑了一些解决方法:
Vec到slice为@trentcl说。但这不适用于 multidimensional Vec。