2015-05-29 20 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,如果你对它感兴趣,你可以在我的更新中链接到的问题中找到更多信息。 –

相关问题