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

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

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

Однако, это ошибка компиляции. Что-то связано с проверкой заимствования и, возможно, с изменчивостью.Нельзя заимствовать как неизменяемый - Строка и длина()

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 действительно заимствованы mutably до его использования в result.len() ,

Я нашел эту проблему в трещине для проверки ржавчины: #6268. Этот выпуск был закрыт в пользу non-lexical borrows RFC issue. Кажется, что это всего лишь одна из тех вещей, которые было бы неплохо иметь, но которые нуждались в большем количестве времени, чтобы быть доступным до 1.0. This сообщение может также представлять определенный интерес (хотя ему почти два года).

+0

Это помогает уточнить. Это больше раздражает, чем что-либо. Таким образом, ошибка связана с конфликтом между «усечением», требующим изменчивости, и «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()'. –

+0

@jocull, вы можете найти больше в вопросах, связанных с моим обновлением, если вы заинтересованы в нем. –