Trying to write a simple virtual machine (bytecode interpreter):
const STACK_SIZE: usize = 1000; mod errors; mod opcodes; mod utils; struct Registers { ... } struct Machine<'a> { registers: Registers, stack: [u64, STACK_SIZE], code: &'a [u8] } impl<'a> Machine<'a> { pub fn new(...) { ... } pub fn fetch(&mut self) -> Result<u8, errors::RuntimeError> { if ... { let next = self.code[self.position()]; ... Ok(next) } else { Err(errors::RuntimeError::EndOfCode) } } pub fn fetch_many(&mut self) -> Result<&[u8], errors::RuntimeError> { if ... { let bytes = &self.code[self.position()..self.position() + n]; ... Ok(bytes) } else { Err(errors::RuntimeError::EndOfCode) } } pub fn position(&self) -> usize { ... } pub fn run(&mut self) { loop { let instruction = self.fetch().expect("unexpected end of code"); match instruction { instruction if instruction == opcodes::Opcode::Push as u8 => { let bytes = self.fetch_many(8).expect("unexpected end of code"); let operand = utils::pack_bytes(bytes); self.stack[self.registers.stack_pointer as usize] = operand; self.registers.stack_pointer -= 1; } _ => {} } } } } }
The problem is in the run function. When I try to compile the code, I get the following error message:
src/main.rs:63:21: 63:80 error: cannot assign to `self.stack[..]` because it is borrowed [E0506] src/main.rs:63 self.stack[self.registers.stack_pointer as usize] = operand; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/main.rs:61:33: 61:37 note: borrow of `self.stack[..]` occurs here src/main.rs:61 let bytes = self.fetch_many(8).expect("end of code"); ^~~~ src/main.rs:63:32: 63:60 error: cannot use `self.registers.stack_pointer` because it was mutably borrowed [E0503] src/main.rs:63 self.stack[self.registers.stack_pointer as usize] = operand; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/main.rs:61:33: 61:37 note: borrow of `*self` occurs here src/main.rs:61 let bytes = self.fetch_many(8).expect("end of code"); ^~~~ src/main.rs:64:21: 64:54 error: cannot assign to `self.registers.stack_pointer` because it is borrowed [E0506] src/main.rs:64 self.registers.stack_pointer -= 1; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/main.rs:61:33: 61:37 note: borrow of `self.registers.stack_pointer` occurs here src/main.rs:61 let bytes = self.fetch_many(8).expect("end of code"); ^~~~ I re-read sections of documentation about ownership (ownership) and borrowing (borrowing), but I still didn’t understand what exactly was wrong with me.
fetch_manyrecord somewhere? Why does he have a mutable link? - D-sidefetch_manychangesself.registers- Daniel Kolesnichenko