[英]Cannot add-assign within `Vec` of user-defined type
考慮以下代碼( 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
}
為什么我只在vec_x
線上得到 E0502? 我不明白為什么只允許ary_x
和vec_i32
的操作。 借用檢查器是否特別對待內置類型( i32
, array
)?
我研究了一些資源並閱讀了我的代碼的 MIR,並設法了解發生了什么。
@trentcl 的評論將是最好的答案。 我盡可能詳細地寫。
對於array
,不使用Index
和IndexMut
特征,編譯器直接操作數組元素(您可以使用 MIR 看到這一點)。 所以,這里不存在借款問題。
解釋Vec
, rustc 指南很有用。
首先, 兩階段借用不適用於vec_foo[0] += vec_foo[1]
語句。
而且, i32
和X
之間的差異是由於操作符降低造成的。
Basically, statements like vec_user_defined[0] += vec_user_defined[1]
are converted to function calls like add_assign(index_mut(...), *index(...))
, and function arguments are evaluated from left to right. 因此, index_mut()
可變地借用x
並且index()
嘗試借用x
,但失敗了。
但是對於像i32
這樣的內置類型,復合賦值運算符不會轉換為 function 調用,並且 rhs 在 lhs 之前被評估(你可以看到index()
在index_mut()
和 MIR 之前被調用)。 因此,對於內置類型, vec_builtin[0] += vec_builtin[1]
有效。
我從lo48576 的文章(日文)中知道了這些事情。
我考慮了一些解決方法:
Vec
轉換為slice
。 但這不適用於多維Vec
。Rust arrays 存在於堆棧中,大小可預測,因此具有更強的借用檢查器保證。 向量是堆棧上的智能指針,指向可以在堆上增長和縮小的數據。 因為最后一個示例使用 Vector 類型,借用檢查器在從堆加載時將整個 Vector 視為單個可變借用的 object。
正如您所觀察到的,借用檢查器可以創建對單個元素的可變引用,以指向存在於堆棧上的東西,而它創建對堆棧上 Vector 智能指針的可變引用,然后進一步可變引用上的數據堆。 這就是對vec_vec_x[1][1]
的不可變引用失敗的原因。
正如@sebpuetz 在評論中指出的那樣,您可以通過首先將不可變引用復制到vec_vec_x[1][1]
來解決此問題,然后創建不可變引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.