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

但是,這是一個編譯錯誤。與借用檢查器有關,可能是可變性。不能借用不可變 - String和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 

但是,如果我稍微改變它允許我這樣做:

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

爲什麼?有沒有辦法改變它,所以它可以寫在一行? (P.S.這是在Rust 1.0上)

回答

9

這是Rust借用檢查程序的一個不幸的缺點。這基本上是因爲

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

相當於

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

,在這裏你可以看到,由於參數在左到右的順序,result確實性情不定地借用計算之前它在result.len()使用。

我在Rust問題跟蹤器中發現此問題:#6268。此問題已關閉,支持non-lexical borrows RFC issue。看起來,這只是其中一件很好的事情,但它需要更多的時間才能完成,因爲它在1.0之前就已經可用了。 This後也可能有一些興趣(即使它幾乎兩歲)。

+0

這有助於澄清。這比任何事情都更令人煩惱。所以這個錯誤與'truncate'需要可變性和'len'需要不可變性之間的衝突有關?看起來'result.len()'在交給截斷之前完成了它的工作,這意味着它比任何東西都更像編譯器怪癖嗎? http://doc.rust-lang.org/std/string/struct.String.html#method.len – jocull

+0

你幾乎是正確的 - 問題是'truncate'需要'&mut self',它禁止任何*後續在同一範圍內借款。是的,它會* *看起來'result.len()'在它交給'truncate()'之前完成,但是,我的答案解釋了爲什麼它不是這樣 - 實際上,方法接收器是在*之前計算的*參數,因此'&mut result'在'result.len()'所要求的''&result'之前的作用域*中。 –

+0

@jocull,如果你對它感興趣,你可以在我的更新中鏈接到的問題中找到更多信息。 –

相關問題