여러 개의 가변 참조로 인해 구조체의 멤버를 자신에게 할당 할 수없는 이유는 무엇입니까? [복제]

Aug 17 2020

내가 할 수 있다고 생각했던 곳에서 빌릴 수 없습니다. 이 경우에 문제를 줄였습니다.

struct A<'a> {
    borrow: &'a mut u8,
}

fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
    a.borrow = a.borrow;
}
error[E0623]: lifetime mismatch
 --> src/lib.rs:6:16
  |
5 | fn does_nothing<'b, 'c>(a: &'b mut A<'c>) {
  |                            -------------
  |                            |
  |                            these two types are declared with different lifetimes...
6 |     a.borrow = a.borrow;
  |                ^^^^^^^^ ...but data from `a` flows into `a` here

그 것 a.borrow의 교회법이 'b'c따라서 여전히 수명이 보장 될 수 없다 'c.

나는 이것에 실제 문제가 없으며 두 수명을 동일하게 만들어서 해결할 수 있지만 왜 이것이 수표를 빌리지 않습니까?


구조체는이 문제를 보여주는 데 중요하지 않은 것처럼 보이며 이중 차입은 쉽게 보여줍니다.

나는 꽤 비슷한 세 가지 기능을 가지고 있지만 어떤 것이 컴파일되고 어떤 오류가 컴파일되지 않는지 알 수 없습니다.

간단한 일반 기능 :

fn only_borrow<T>(a: &mut T) {
    *a = *a;
}

오류가 발생합니다.

error[E0507]: cannot move out of `*a` which is behind a mutable reference
 --> src/lib.rs:2:10
  |
2 |     *a = *a;
  |          ^^ move occurs because `*a` has type `T`, which does not implement the `Copy` trait

추가 수준의 간접 참조를 포함하면 오류가 변경됩니다.

fn only_borrow_double<T>(a: &mut &mut T) {
    *a = *a;
}
error[E0623]: lifetime mismatch
 --> src/lib.rs:2:10
  |
1 | fn only_borrow_double<T>(a: &mut &mut T) {
  |                             -----------
  |                             |
  |                             these two types are declared with different lifetimes...
2 |     *a = *a;
  |          ^^ ...but data from `a` flows into `a` here

암시 된 수명에서 벗어나 변경하면 오류를 수정할 수 있습니다.

fn working_double<'b, T>(a: &'b mut &'b mut T) {
    *a = *a;
}

답변

Emoun Aug 18 2020 at 09:59

당신은 당신의 생애를 살펴 걸릴해야합니다 'b'c:

  • &'b mut ..."시간"동안 유효하고 유효한 참조가 있음을 의미합니다 'b.
  • A<'c>에 대해 유효하고 유효한 객체가 있음을 의미합니다 'c.

당신이 가지고 있지 않은 것은이 두 생애 사이의 특정한 관계입니다. 컴파일러가 추론 할 수있는 유일한 이후이다 A<'c>뒤에 &'b, 'c보다 오래 있어야 'b할 때마다 즉, 'b유효하므로입니다 'c. 결정적으로는 그 반대가 아닙니다.

보시다시피 컴파일러 는 동일한 수명을 요구 'b하며 'c동일 해야합니다 . 왜 이런거야?

우리의 가능성을 살펴 보겠습니다.

  1. 'c그리고 'b관계가 없다 : 어떤 관계도없이 컴파일러는 무엇을 넣었는지에 대해 어떤 것도 보장 할 수없고 A.borrow따라서 그것을 허용하지 않는다는 것을 쉽게 알 수있다.
  2. 'c엄격히 오래 지속됩니다. 'b즉, 일부 장소 'c는 유효 'b하지 않습니다. 수명
    a.borrow = a.borrowa사용 하는 재 차입이 됩니다 'b. 이 대답은 그 이유를 설명합니다 . 그러나 이것은 a이제 'b수명에 따라 달라 지며, 일부 시간 동안 유효하지 않은 a것은 유효합니다 ( a수명이 있기 때문에 'c). 이것은 오류를 제공합니다.
  3. 'b엄격히 오래 살아남습니다 'c: 우리가이 관계를 가졌다면 그것은 효과가있을 것입니다. 요청한 것보다 "더 큰"수명 ( 'b)을 얻으므로 재차 입은 유효합니다 'c. 그러나 우리는 이미 'c: 'b뒤에서 컴파일러에 의해 추론되었습니다. 따라서이 수명을 추가하면 두 수명이 동일 해지며 시작된 곳으로 돌아갑니다.
struct A<'a> {
    borrow: &'a mut u8,
}

/// We add the relation 'b: 'c
fn does_nothing<'b: 'c, 'c>(a: &'b mut A<'c>) {
    a.borrow = a.borrow;
}