2015-02-16 2 views
0

Я потратил много бесплодных часов, пытаясь заставить это работать, но я боюсь, что мой единственный ресурс теперь - попытаться обобщить мой код и попросить всех вас о помощи.Хранение изменчивых ссылок и сроков жизни

ситуация, если я раскомментировать два экземпляра mut в следующем коде, он больше не компилирует (а не по причине того, что имеет смысл для меня):

use std::cell::RefCell; 
use std::ops::Index; 

struct Foo<'a, T: 'a> { 
    t_array: [T; 3], 
    t_refs: RefCell<Vec<&'a /* mut */ T>>, //'   // 1 
} 
impl<'a, T> Foo<'a, T> { 
    fn new(t1: T, t2: T, t3: T) -> Foo<'a, T> { //' 
     Foo { 
      t_array: [t1, t2, t3], 
      t_refs: RefCell::new(Vec::with_capacity(3)) 
     } 
    } 
    fn add_t_ref(&'a mut self, at_index: usize) { //' 
     let t_ref = & /* mut */ self.t_array[at_index]; // 2 
     let mut t_refs = self.t_refs.borrow_mut(); 
     t_refs.push(t_ref); 
    } 
} 
impl<'a, T> Index<usize> for Foo<'a, T> { 
    type Output = T; 
    #[inline] 
    fn index(&self, index: &usize) -> &T { 
     let t_refs = self.t_refs.borrow(); 
     t_refs[*index] 
    } 
} 

Ошибка, которая возникает, когда вместо того, чтобы хранить mut рефов в Vec является:

blah3_mut.rs:26:9: 26:15 error: `t_refs` does not live long enough 
blah3_mut.rs:26   t_refs[*index] 
         ^~~~~~ 
blah3_mut.rs:24:42: 27:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 24:41... 
blah3_mut.rs:25:42: 27:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 25:41 

Я бы рад, если кто-то может объяснить, почему это происходит; интуитивно кажется, что не должно быть проблемой, что заимствование RefCell выходит за рамки. Vec (и, следовательно, RefCell тоже) не имеют данных, на которые указывает ссылка, так почему компилятор заботится о времени жизни своих ссылок?

P.S. Я знаю, что мой упрощенный фрагмент кода не делает это очевидным, почему я хранить изменяемые ссылки в Vec или почему я использую RefCell -suffice сказать, что это не случайно, хотя

P.P.S. Я попытался Мессинг вокруг немного с пожизненной аннотации о методе index и/или связанного типа признака, но до сих пор только удалось получить различные ошибки делать что

ответ

2

Причина он работает с непреложным ссылок потому, что те могут быть неявно скопирован. Когда вы переключитесь на попытку вернуть &mut, тогда будет два места, которые имеют эту ссылку - Vec и вызывающую функцию. Это введет aliasing, а изменчивые псевдонимы не допускаются в Rust.

Вы можете даже игнорировать Index реализацию и просто попробуйте это:

fn main() { 
    let mut f = Foo::new(1,2,3); 
    f.add_t_ref(1); 
    f.add_t_ref(2); 
} 

Вы получите:

error: cannot borrow `f` as mutable more than once at a time 

Хотя все это верно, это не объясняет, почему вы получаете конкретные сообщения об ошибках, которые вы делаете.

Смежные вопросы