2013-12-09 1 views
5

я следующий (достаточно невинный) Ржавчина Код:не может занимать Foo, как неизменны, потому что он также заимствованы, как изменяемый

let file = &Path(some_file_name); 
let mut buf = [0u8, ..12]; 
match io::file_reader(file) { 
    Ok(reader) => reader.read(buf, buf.len()), 
    Err(msg) => println(msg) 
} 

rustc жалуется, что

не может занимать buf[] непреложными, потому что это также заимствованные как изменчивые

При изменении соответствующей строки на:

Ok(reader) => reader.read(buf, 12), 

все будет работать нормально. Но это менее удовлетворительно, так как теперь длина буфера дублируется в коде. Хотя смутно понимая, почему rustc жалуется, мне все же хотелось бы утверждать, что rustc должен иметь возможность сделать вывод, что len() является чистой функцией и не имеет побочного эффекта, поэтому код действителен. Кроме того, довольно распространенный паттен, чтобы читать в буфер таким образом.

Так что же такое идиоматический путь ржавчины?

EDIT: Код был для Rust 0.8. Как отметил @pnkfelix, с тех пор был изменен API Reader.read. Второй параметр больше не нужен.

+0

Забота о предоставлении полного кода? Я объединил что-то, основанное на вашем коде, но у меня другая ошибка. Какую версию ржавчины вы используете? – asm

+0

BTW, '~ Path' выделяет поле для' Path', когда можно просто поместить Path прямо в стек и принять нормальную ссылку на него, например. '& Path'. – huon

+0

Андрей, код был для ржавчины 0.8. дбаупп, да. '& Path' было бы лучше. – edwardw

ответ

7

Этот ответ для моей версии rustc: rustc 0,9-до (61443dc 2013-12-01)

  1. Текущая версия считывателей признака имеет другой интерфейс, чем тот, который был указан. Вместо того, чтобы брать оба (срез) выходного буфера и длину, теперь он просто принимает (срез) выходного буфера. Он может получить длину выходного буфера из среза, поэтому вам не нужно повторять себя.

  2. Причина, по которой Rust жалуется, заключается в том, что она пытается обеспечить, чтобы у вас не было чтения/записи наложения памяти. Он пытается остановить вас от передачи неизменяемого заимства buf в один контекст и изменчивого заимства buf в другой контекст.

    • Когда вы говорите len() это чистая функция, я понимаю, вы имеете в виду, что он не пишет какое-либо изменяемое состояние. Однако в общем случае это может быть чтение изменчивое состояние. (Это не так, потому что мы имеем дело с буфером фиксированного размера. Но все же, в общем, можно представить, что мы имеем дело с некоторой абстракцией массива с автоматическим изменением размера.)

    • Итак, есть эффект, только тот, о котором люди часто не думают: о чтении.

    • Я подозреваю, что идиоматический способ решения проблемы, которую вы видели (игнорируя тот факт, что API изменился), состоял бы в том, чтобы избежать наложения перекрытий на buf, например.как так:

      Ok(reader) => { let l = buf.len(); reader.read(buf, l) },

Таким образом, вы не повторять себя; вы просто предоставляете два неперекрывающихся экстента, где buf заимствован по-разному.

+0

Это имеет смысл. Спасибо, pnkfelix. – edwardw