2017-09-26 5 views
1

Cell (UnsafeCell/RefCell/...) 참조 수명에 문제가 있습니다. 해결하려고 할 때왜 빌 셀쳐에 '셀'이 특별한가요?

error[E0308]: mismatched types 
--> src/main.rs:4:29 
    | 
4 |  let x2: Cell<&'a u32> = x; 
    |       ^lifetime mismatch 
    | 
    = note: expected type `std::cell::Cell<&'a u32>` 
      found type `std::cell::Cell<&'b u32>` 
note: the lifetime 'a as defined on the function body at 3:1... 
--> src/main.rs:3:1 
    | 
3 |/fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
4 | |  let x2: Cell<&'a u32> = x; 
5 | | } 
    | |_^ 
note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 3:1 
--> src/main.rs:3:1 
    | 
3 |/fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
4 | |  let x2: Cell<&'a u32> = x; 
5 | | } 
    | |_^ 

내가 <>에서 :하지 잘 알려진 연산자 생각하지만 난 어떤 RFC에 그것을 발견 :

fn test1<'a, 'b: 'a>(x: Cell<&'b u32>) { 
    let x2: Cell<&'a u32> = x; 
} 

를하지만 오류가 발생합니다 : 나의 이해에서이 코드를 컴파일한다 내 문제.

수명이 더 긴 Cell을 오래 사용할 수 있어야합니다. Cell을 더미 래퍼로 바꾸면 모든 것이 잘 작동하므로 참조 수명을 다룰 때 Cell (UnsafeCell 등)이 특별히 처리됩니다.

이것은 원래의 문제는 아닙니다. 두 개의 구조 사이에 공유 된 상태를 하나 갖고 싶습니다. RefCell이있는 하나의 기본 구조체와 RefCell을 참조하는 자식 구조체가 있지만 전체 개체의 수명 동안 자체를 빌려주지 않으면 빌려주는 검사기가 행복하지 않습니다. 참조 :

struct A<'a> { 
    x: RefCell<&'a u32>, 
} 

impl<'a> A<'a> { 
    fn new(x: &'a u32) -> A<'a> { 
     A { x: RefCell::new(x) } 
    } 

    fn foo(&self) -> B<'a> { 
     B { x: &self.x } 
    } 
} 

struct B<'a> { 
    x: &'a RefCell<&'a u32>, 
} 

을 내가 fooself에 평생 'a 추가하면 컴파일하지만이 코드 실패 :

let fs = A::new(&x); 
{ 
    fs.foo(); 
} 
let fs2 = fs; 

오류 : 오류가 [E0505은] : fs 밖으로 이동할 수 없습니다 것은이 있기 때문에 빌려준

개체간에 공유 상태를 구현하는 다른 방법이 있습니까? 나는 하나의 스레드를 사용하고 있으므로 지금은 동기화 문제가 없다.

+1

가에 대한 설명 https://doc.rust-lang.org/nomicon/subtyping.html를 참조하십시오 '저장된 유형을 변형시킬 수 있습니다. – interjay

+1

'Cell '''Cell'은'&'-ref에 저장 될 때 변형 될 수 있기 때문에'Tiny'에 대해 불변합니다. 차이를 허용하면' x32.set (somethingWithLifetimeA); x.get() // 실제로 & a '에 대해서만 살아남는 T) –

+0

자료를 가리키고 예제를 제공 해주셔서 감사합니다. 차이가 어떻게 작용하는지! 이것은 나를 이해하는 데 도움이되었습니다. 검사기를 빌려 내 문제에 대한 해결책을 내놓으십시오. Didnt는 그렇게 빨리 해상도를 찾을 것을 기대한다 :) – Rafalh

답변

3

의견에서 설명한대로 내 문제는 Cell type invariance에 의해 발생했습니다. 나는 같은 생애를 사방에 두 번 사용하지 않고 두 가지 수명을 사용하여 원래의 문제를 해결했습니다. 이제 &self'a보다 짧은 수명에 대한 foo에서 빌려 :`셀 수 있도록하는 것이 안전하지 않을 이유

struct A<'a> { 
    x: RefCell<&'a u32>, 
} 

impl <'a> A<'a> { 
    fn new(x: &'a u32) -> A<'a> { 
     A { 
      x: RefCell::new(x), 
     } 
    } 

    fn foo<'b>(&'b self) -> B<'b, 'a> { 
     B { 
      x: &self.x, 
     } 
    } 
} 

struct B<'b, 'a: 'b> { 
    x: &'b RefCell<&'a u32>, 
}