2016-12-16 20 views
8

Ten kod nie bał sprawdzania pożyczyć (playground):Zmienna pożyczyć od siebie nie zmienia się na niezmiennej

struct Data { 
    a: i32, 
    b: i32, 
    c: i32, 
} 

impl Data { 
    fn reference_to_a(&mut self) -> &i32 { 
     self.c = 1; 
     &self.a 
    } 
    fn get_b(&self) -> i32 { 
     self.b 
    } 
} 

fn main() { 
    let mut dat = Data{ a: 1, b: 2, c: 3 }; 
    let aref = dat.reference_to_a(); 
    println!("{}", dat.get_b()); 
} 

Błąd:

error[E0502]: cannot borrow `dat` as immutable because it is also borrowed as mutable 
    --> <anon>:19:20 
    | 
18 |  let aref = dat.reference_to_a(); 
    |    --- mutable borrow occurs here 
19 |  println!("{}", dat.get_b()); 
    |     ^^^ immutable borrow occurs here 
20 | } 
    | - mutable borrow ends here 

Może ktoś dokładnie wyjaśnić, dlaczego tak jest? Wydaje mi się, że zmienna zapożyczona z dat jest przekształcana w niezmienną po powrocie, ponieważ funkcja ta zwraca tylko niezmienne odniesienie. Czy narzędzie wypożyczające nie jest jeszcze wystarczająco sprytne? Czy to jest planowane? Czy jest jakiś sposób obejścia tego?

+5

[Limits of Lifetimes] (https://doc.rust-lang.org/nomicon/lifetime-mismatch.html). To jest dokładnie to samo. – aSpex

+0

@Stargateur: Nie sądzę, że kod "desugared" ma na celu skompilować; to tylko dla zilustrowania. – Timmmm

+0

@Stargateur: Nie, to nie pomaga. Konieczne jest ograniczenie czasu życia 'pożyczki' https://play.rust-lang.org/?gist=fc564b89ff4fa44ae5463d7f407e88ca&version=stable&backtrace=0 – aSpex

Odpowiedz

1

Cykl życia zależy od tego, czy odniesienie jest zmienne czy nie. Praca za pomocą kodu:

fn reference_to_a(&mut self) -> &i32 

Chociaż wcieleń zostały pomijana, jest to równoznaczne z:

fn reference_to_a<'a>(&'a mut self) -> &'a i32 

czyli czasy życia wejściowe i wyjściowe są takie same. Jest to jedyny sposób na przypisanie wcieleń do takiej funkcji (chyba, że ​​zwróci odniesienie &'static do danych globalnych), ponieważ nie można uzupełnić czasu życia z niczego.

Oznacza to, że jeśli utrzymasz wartość zwrotną przy życiu, zapisując ją w zmiennej, utrzymasz przy życiu również &mut self.

Innym sposobem myślenia jest to, że &i32 jest sub-pożyczką &mut self, jest zatem ważny tylko do momentu wygaśnięcia.

Jak zauważa @spex, jest to covered in the nomicon.

+0

Dzięki, czy istnieje rozwiązanie lub obejście problemu? Czy nieliczne okresy życia naprawią to? – Timmmm

+1

Nie sądzę, że istnieje obejście inne niż podział mutacji na osobne wywołanie metody. To nie jest leksykalna rzecz życia; '& i32' jest pożyczony * od *' & mut self', więc są one zasadniczo powiązane. –