2015-10-01 20 views
6

Bir oyunda bir varlık sistemi için kod yazmaya çalışıyorum ama bu hatayı alıyorum, böylece kodu aynı şey yapan bir şeye kaynatıyorum. gerçek kodda aynı hata.Yapı yönteminde borç alma hatası hakkında karışık

Neden derleyici bana self.my_list referansının baz işlevi bittiğinde kapsam dışı kaldığını anlatıyor.

Benim pas sürümü for döngü sona erdiğinde kapsam dışında gider ben sanırdım rustc 1.3.0 (9a92aaf19 2015-09-15)

mı?

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

... –

+2

Bu yalnızca oluşur for döngüsü içindeki başvuruları döndürürsünüz. Sorununuzun MCVE adresi şudur: http://is.gd/dJFkUz –

+2

[Desugared sürümü] (http://is.gd/atsegO) aynı sorunu yaşar. Bu kesinlikle bir hata gibi hissettiriyor ... – Shepmaster

cevap

1

Bu ariyet denetleyicisi bir sınırlamadır:

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); 
    } 
} 

Bu

alıyorum hata mesajıdır. İşlevin güvenli olduğunu düşündüğünüz yol aslında işlevi iki yol olarak ele alır: işlevin Some(x) döndürdüğü yol boyunca, my_list'u tekrar ödünç almazsınız ve işlevin None değerini döndürdüğü yol boyunca borç ödemeleri sona erer for döngüsünden sonra.

Bu, borç denetçisinin işleve bakış açısı değil; Borç denetleyicisi, sözcük kapsamları açısından çalışır. Mümkün olduğunca dar bir kapsam seçmeye çalışır, ancak gerekirse tüm işlevi kapsam olarak ele alır. Geri dönüş değerindeki ömrünün self kullanım ömrü ile aynı olduğunu, bu nedenle x ile referans verilen değerin ömürlerinin self ile aynı olması gerektiğini, dolayısıyla &self.my_list ödününün aynı ömre sahip olması gerektiğini görür, bu nedenle borç alır Fonksiyonun geri dönüşünün ötesinde. Farklı olarak işlev yazarsanız

, Pas onu kabul edecektir: Aynı hata oluşursa kendi kapsamı içine döngü koymak bile ... garip

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

* tarafından düzeltilmesi büyük olasılıkla, borç denetleyicisi, sözcük kapsamları * açısından çalışır - bu durumda ayrı bir sözcük kapsamı yardımcı olmaz. [Desugared sürümü] (http://is.gd/atsegO) veya [şekilli sürüm] (http://is.gd/EHmRrU) her ikisi de yardımcı olmayan sözcüksel kapsamlara sahiptir. – Shepmaster

+0

Netleştirmeye çalıştım. Değişkenlerin kapsamı önemli değil; Sorun, derhal sözcük kapsamının ötesinde genişletilebilen borç kapsamıdır. –

İlgili konular