[rust] 중첩 배열 인덱스에서 “변경 가능으로 빌려서 변경 불가능한 것으로 빌릴 수 없음”은 무엇을 의미합니까?

이 경우 오류의 의미는 무엇입니까?

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

그 색인이를 통해 구현된다 발견 IndexIndexMut특성과 그 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;


답변