2015-05-29 21 views
7
let mut result = String::with_capacity(1000); 

result.push_str("things... "); 
result.push_str("stuff... "); 

result.truncate((result.len() - 4)); 

Jest to jednak błąd kompilacji. Coś związanego z korektą pożyczki i ewentualnie zmiennością.Nie można zaciągnąć pożyczki jako niezmiennej - String i len()

error[E0502]: cannot borrow `result` as immutable because it is also borrowed as mutable 
--> <anon>:7:22 
    | 
7 |  result.truncate((result.len() - 4)); 
    |  ------   ^^^^^^   - mutable borrow ends here 
    |  |    | 
    |  |    immutable borrow occurs here 
    |  mutable borrow occurs here 

Jednak gdybym nieznacznie zmienić go wolno mi to zrobić:

let newlen = result.len() - 4; 
result.truncate(newlen); 

Dlaczego? Czy istnieje sposób, aby to zmienić, aby można było napisać w jednym wierszu? (P.S. jest na Rust 1.0)

Odpowiedz

9

Jest to niefortunna wada procedury sprawdzania wypożyczeń Rust. To w istocie się dzieje, ponieważ

result.truncate(result.len() - 2) 

jest równoważna

String::truncate(&mut result, result.len() - 2) 

i tutaj widać, że ponieważ argumenty są obliczane od lewej do prawej kolejności result rzeczywiście pożyczył mutably zanim zostanie użyta w result.len() .

Znalazłem ten problem w narzędziu do wykrywania problemów z rdzą: #6268. Ten problem został zamknięty na rzecz non-lexical borrows RFC issue. Wydaje się, że jest to jedna z tych rzeczy, która byłaby miła, ale która potrzebowała więcej czasu, aby była dostępna przed 1.0. This post może również być interesujące (mimo że ma prawie dwa lata).

+0

To pomaga wyjaśnić. To bardziej irytujące niż cokolwiek innego. Więc błąd jest związany z konfliktem między 'truncate' wymagającym zmienności i' len' wymagającym niezmienności? Wydawałoby się, że 'result.len()' zakończyłoby pracę przed przekazaniem do skracania, co oznacza, że ​​jest to bardziej dziwactwo kompilatora niż cokolwiek innego? http://doc.rust-lang.org/std/string/struct.String.html#method.len – jocull

+0

Masz prawie rację - problem polega na tym, że 'truncate' wymaga' & mut self ', co zabrania * dowolnej * kolejnej pożyczanie w tym samym zakresie. I tak, to * mogłoby * wydawać się, że 'result.len()' jest zakończone zanim zostanie przekazane do 'truncate()', jednak moja odpowiedź wyjaśnia, dlaczego tak nie jest - w rzeczywistości, metoda method została obliczona * przed * argumenty, a więc '& mut result' ma zasięg * przed *' & result' wymagany przez 'result.len()'. –

+0

@jocull, możesz znaleźć więcej problemów związanych z moją aktualizacją, jeśli jesteś zainteresowany. –

Powiązane problemy