2015-10-01 9 views
6

Próbuję napisać jakiś kod dla systemu encji w grze, ale dostaję ten błąd, więc ugotowałem kod w coś, co robi to samo, dostaję ten sam błąd w faktycznym kodzie.Mylić o błędzie wypożyczenia w metodzie struct

Nie rozumiem, dlaczego kompilator mówi mi, że odniesienie do self.my_list wykracza poza zakres, kiedy kończy się funkcja baz.

Moja wersja rdza jest rustc 1.3.0 (9a92aaf19 2015-09-15)

bym nie pomyślał, że to wykracza poza zakres, gdy pętla for kończy?

struct Foo { 
    name : &'static str, 
} 

struct Bar { 
    my_list : Vec<Foo>, 
} 

impl Bar { 
    fn New() -> Bar { 
     let mut new_instance = Bar { my_list : vec!() }; 
     new_instance.my_list.push(Foo { name : "foo1" }); 
     new_instance.my_list.push(Foo { name : "foo2" }); 
     new_instance.my_list.push(Foo { name : "foo3" }); 
     return new_instance; 
    } 

    fn Baz(&mut self, name : &'static str) -> Option<&Foo> { 
     for x in &self.my_list { 
      if x.name == name { 
       return Some(x); 
      } 
     } 

     self.my_list.push(Foo { name : "foo" }); 

     return None; 
    } 
} 

fn main() { 
    let mut bar = Bar::New(); 
    if let Some(x) = bar.Baz("foo1") { 
     println!("{} found", x.name); 
    } 
} 

To jest komunikat o błędzie, który pojawia się:

Compiling tutorial v0.1.0 (file:///C:/Code/Projects/rust/tutorial) 
src\main.rs:35:9: 35:21 error: cannot borrow `self.my_list` as mutable because it is also borrowed as immutable 
src\main.rs:35   self.my_list.push(Foo { name : "foo" }); 
         ^~~~~~~~~~~~ 
src\main.rs:29:19: 29:31 note: previous borrow of `self.my_list` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `self.my_list` until the borrow ends 
src\main.rs:29   for x in &self.my_list { 
           ^~~~~~~~~~~~ 
note: in expansion of for loop expansion 
src\main.rs:29:9: 33:10 note: expansion site 
src\main.rs:38:6: 38:6 note: previous borrow ends here 
src\main.rs:28  fn Baz(&mut self, name : &'static str) -> Option<&Foo> { 
... 
src\main.rs:38  } 
       ^
error: aborting due to previous error 
Could not compile `tutorial`. 

To learn more, run the command again with --verbose. 
+0

to dziwne ... nawet jeśli włożysz do pętli na własnym zakresie występuje ten sam błąd ... –

+2

Dzieje się tak tylko wtedy, gdy zwracasz referencje w pętli for. MCVE twojego problemu jest tutaj: http://is.gd/dJFkUz –

+2

Wersja [wersja odrzucona] (http://is.gd/atsegO) doświadcza tego samego problemu. To z pewnością jest jak błąd ... – Shepmaster

Odpowiedz

1

To ograniczenie sprawdzania pożyczyć. Sposób, w jaki rozumujesz, że funkcja jest bezpieczna, zasadniczo traktuje funkcję jako dwie ścieżki: wzdłuż ścieżki, gdzie funkcja zwraca Some(x), ponownie nie pożyczasz my_list, a wzdłuż ścieżki, gdzie funkcja zwraca None, kończy się pożyczanie po pętli for.

To nie jest sposób, w jaki sprawdzający pożyczkę sprawdza funkcję; sprawdzarka wypożyczeń działa w zakresie zakresów leksykalnych. Próbuje wybrać zakres tak wąski, jak to możliwe, ale w razie potrzeby potraktuje całą funkcję jako zakres. Okazuje się, że czas życia w wartości zwracanej jest taki sam, jak czas życia self, dlatego czas życia wartości, do której odnosi się x, musi być taki sam jak self, dlatego też pożyczony &self.my_list musi mieć to samo życie co self, dlatego pożyczenie trwa poza zwrot funkcji.

Jeśli piszesz funkcję inaczej, Rust zaakceptuje go:

fn Baz(&mut self, name : &'static str) -> Option<&Foo> { 
    match self.my_list.iter().position(|x| x.name == name) { 
     Some(i) => Some(&self.my_list[i]), 
     None => { 
      self.my_list.push(Foo { name : "foo" }); 
      None 
     } 
    } 
} 
+0

* Sprawdzanie wypożyczeń działa w kategoriach zakresów leksykalnych * - z wyjątkiem tego przypadku , oddzielny zakres leksykalny nie pomaga. Wersja [wersja desugared] (http://is.gd/atsegO) lub [wersja z cukrem] (http://is.gd/EHmRrU) mają zakresy leksykalne, które nie pomagają. – Shepmaster

+0

Próbowałem wyjaśnić. Zakres zmiennych nie ma znaczenia; problemem jest zakres pożyczania, który można rozszerzyć poza najbliższy zakres leksykalny. –

Powiązane problemy