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

Tuttavia, questo è un errore di compilazione. Qualcosa che ha a che fare con il controllore del prestito e possibilmente con la mutevolezza.Impossibile prendere in prestito come immutabile - String and 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 

Eppure, se cambio leggermente mi è permesso di fare questo:

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

Perché? C'è un modo per cambiare questo in modo che possa essere scritto in una riga? (P.S. questo è su Rust 1.0)

risposta

9

Questa è una sfortunata carenza di procedura di controllo dei prestiti di ruggine. Questo accade essenzialmente perché

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

è equivalente a

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

e qui si può vedere che, poiché gli argomenti sono calcolati in sinistra a destra ordine, result è infatti in prestito mutably prima del suo utilizzo in result.len() .

Ho trovato questo problema in Rust issue tracker: #6268. Questo problema è stato chiuso a favore di non-lexical borrows RFC issue. Sembra che sia solo una di quelle cose che sarebbe bello avere ma che aveva bisogno di più tempo per essere fatto che fosse disponibile prima della 1.0. Il post This potrebbe anche essere di qualche interesse (anche se ha quasi due anni).

+0

Questo aiuta a chiarire. È più di un fastidio che altro. Quindi l'errore è legato a un conflitto tra 'truncate' che richiede mutabilità e' len' che richiede immutabilità? Sembrerebbe che 'result.len()' avrebbe completato il suo lavoro prima di passare a troncare, il che significa che si tratta più di una stranezza del compilatore che altro? http://doc.rust-lang.org/std/string/struct.String.html#method.len – jocull

+0

Hai quasi ragione - il problema è che 'truncate' richiede' & mut self 'che proibisce * qualsiasi * successivo prendere in prestito nello stesso ambito. E sì, * sembrerebbe * che 'result.len()' sia completato prima che venga passato a 'truncate()', tuttavia, la mia risposta spiega perché non è così - in realtà, il ricevitore del metodo è calcolato * prima * argomenti, e quindi '& mut result' è in ambito * prima * * e result' richiesto da' result.len() '. –

+0

@jocull, puoi trovare ulteriori informazioni sui problemi a cui sono collegato nel mio aggiornamento, se sei interessato a questo. –