이 경우 오류의 의미는 무엇입니까?
fn main() {
let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
v[v[1]] = 999;
}
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:3:7
|
3 | v[v[1]] = 999;
| --^----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
그 색인이를 통해 구현된다 발견 Index
및 IndexMut
특성과 그 v[1]
에 대한 문법 설탕입니다 *v.index(1)
. 이 지식을 갖추고 다음 코드를 실행하려고했습니다.
use std::ops::{Index, IndexMut};
fn main() {
let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
*v.index_mut(*v.index(1)) = 999;
}
놀랍게도, 이것은 완벽하게 작동합니다! 첫 번째 스 니펫은 왜 작동하지 않지만 두 번째 스 니펫은 작동합니까? 내가 문서를 이해하는 방식은 동일해야하지만 분명히 그렇지 않습니다.
답변
설탕 제거 버전은 현재와 약간 다릅니다. 라인
v[v[1]] = 999;
실제로 설탕을 빼다
*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
결과적으로 동일한 오류 메시지가 표시되지만 주석은 현재 상황에 대한 힌트를 제공합니다.
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:7:48
|
7 | *IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
| ------------------- ------ ^^ immutable borrow occurs here
| | |
| | mutable borrow occurs here
| mutable borrow later used by call
설탕 제거 버전과의 중요한 차이점은 평가 순서입니다. 함수 호출의 인수는 실제로 함수 호출을 수행하기 전에 나열된 순서대로 왼쪽에서 오른쪽으로 평가됩니다. 이 경우 이것은 첫 번째 &mut v
가 평가되고, 차용이 가능 하다는 것을 의미합니다 v
. 다음 Index::index(&v, 1)
으로 평가해야하지만 불가능합니다 – v
이미 변경이 가능합니다 . 마지막으로, 컴파일러는에 대한 함수 호출에 변경 가능한 참조가 여전히 필요하다는 것을 보여 index_mut()
주므로 공유 참조를 시도 할 때 변경 가능한 참조는 여전히 유효합니다.
실제로 컴파일하는 버전은 평가 순서가 약간 다릅니다.
*v.index_mut(*v.index(1)) = 999;
먼저, 메소드 호출에 대한 함수 인수는 왼쪽에서 오른쪽 *v.index(1)
으로 평가됩니다. 즉, 먼저 평가됩니다. 이로 인해 usize
임시 공유 차용을 v
다시 해제 할 수 있습니다. 그런 다음의 수신자 index_mut()
가 평가됩니다. 즉, 변경 가능하게 v
차용됩니다. 공유 차용이 이미 확정되었으므로 전체 표현식이 차용 검사기를 통과하기 때문에 이것은 잘 작동합니다.
컴파일되는 버전은 “비-어휘 수명”이 도입 된 이후에만 컴파일됩니다. 이전 버전의 Rust에서 공유 차용은 표현식이 끝날 때까지 유효하며 유사한 오류가 발생합니다.
내 생각에 가장 깨끗한 해결책은 임시 변수를 사용하는 것입니다.
let i = v[1];
v[i] = 999;