Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

the method `fold` exists for reference `&[T]`, but its trait bounds were not satisfied, I don't understand the given bounds in question

So I’m building a chip-8 CPU emulator and to make copying data into the memory I created the following two methods:

pub struct CPU {
    // ... other unrelated fields
    pub memory: [u8; 0x1000],
}

impl CPU {
    pub fn raw_copy_to_mem(&mut self, loc: usize, data: &[u8]) {
        data.chunks(2).fold(loc, |loc, bytes| {
            self.raw_add_to_mem(loc, *bytes.first().unwrap(), *bytes.last().unwrap())
        });
    }

    pub fn raw_add_to_mem(&mut self, loc: usize, high: u8, low: u8) -> usize {
        self.memory[loc] = high; self.memory[loc + 1] = low;
        loc + 2
    }
}

Now this works for this for example:

fn make_cpu() -> processor::CPU {

   processor::CPU {
        // ... other unrelated fields
        memory: [0; 0x1000],
    }
}
#[test]
fn test_raw_memory_copy() {
    let mut cpu = make_cpu();

    let add_twice: [u8; 6] = [
        0x80, 0x14,
        0x80, 0x14,
        0x00, 0xEE,
    ];

    cpu.raw_copy_to_mem(0x100 , &add_twice);

    assert_eq!(cpu.memory[0x100..0x106], add_twice);

}

Now to make doing OpCodes easier I have the following struct and functions:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#[derive(Debug, Clone, Copy)]
pub struct OpCode(u8, u8);

impl OpCode {
    pub fn high_byte(&self) -> u8 {
        self.0
    }

    pub fn low_byte(&self) -> u8 {
        self.1
    }
}

impl From<OpCode> for u16 {
    fn from(c: OpCode) -> Self {
        (c.0 as u16) << 8 | c.1 as u16
    }
}

impl From<&OpCode> for u16 {
    fn from(c: &OpCode) -> u16 {
        c.into()
    }
}

impl OpCode {
    pub fn add(h: u8, l: u8) -> Self {
        Self (0x8 << 4 | h, (l << 4) | 4)
    }
}

And the following CPU function also works great:

impl CPU {
    pub fn add_to_mem(&mut self, loc: usize, oc: &OpCode) -> usize {
        self.memory[loc] = oc.high_byte(); self.memory[loc + 1] = oc.low_byte();
        loc + 2
    }
}

The problem occurs when I try to add a copy_to_mem() function for the OpCode struct:

impl CPU {
    pub fn copy_to_mem(&mut self, loc: usize, data: &[OpCode]) {
        data.fold(loc, |loc, opcode| {
            self.add_to_mem(loc, opcode)
        });
    }
}

I get the following error that I only vaguely understand:

error[E0599]: the method `fold` exists for reference `&[OpCode]`, but its trait bounds were not satisfied
  --> src/processor.rs:21:14
   |
21 |         data.fold(loc, |loc, bytes| {
   |              ^^^^ method cannot be called on `&[OpCode]` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `&[OpCode]: Iterator`
           which is required by `&mut &[OpCode]: Iterator`
           `[OpCode]: Iterator`
           which is required by `&mut [OpCode]: Iterator`

I get that it’s saying that whilst there is a fold() function & that it can’t call it because some trait bounds weren’t satisfied so it can’t call it but it doesn’t state what those bounds are in a way that I can understand.

So, could someone explain what is going on, and how to fix?

>Solution :

The error message is misleading: the problem is that you’re trying to use a slice as an iterator, but it isn’t. To obtain an iterator for the slice, call it’s iter() method (or iter_mut() for mutable iterator).

pub fn copy_to_mem(&mut self, loc: usize, data: &[OpCode]) {
    data.iter().fold(loc, |loc, bytes| {
        self.add_to_mem(loc, bytes.high_byte())
    });
}

Note that it’ll still error with:

error[E0308]: mismatched types
  --> src/lib.rs:60:34
   |
60 |             self.add_to_mem(loc, bytes.high_byte())
   |                                  ^^^^^^^^^^^^^^^^^ expected `&OpCode`, found `u8`

Because add_to_mem expects &OpCode but while bytes is indeed &OpCode bytes.high_byte() is u8.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading