rusttuplesreturnownershipborrow

Rust private function throws error when trying to return tuple of values


I have a function I am attempting to return a tuple of values from:

fn get_two_bytes(data: &[u8]) -> (Vec<(u8, u8)>, BTreeSet<(u8, u8)>) {
    let two_byte_vec = data
        .chunks(2)
        .map(|x| (x[0], x[1]))
        .collect::<Vec<_>>();

    let mut two_byte_set : BTreeSet<&(u8, u8)> = BTreeSet::new();
    for n in &two_byte_vec {
        two_byte_set.insert(n);
    }

    return (two_byte_vec, two_byte_set);
}

This error is generated:

error[E0308]: mismatched types
  --> src/lib.rs:13:27
   |
13 |     return (two_byte_vec, two_byte_set);
   |                           ^^^^^^^^^^^^ expected tuple, found `&(u8, u8)`
   |
   = note: expected struct `BTreeSet<(u8, u8)>`
              found struct `BTreeSet<&(u8, u8)>`

I don't want to return &two_byte_set obviously - I want to transfer ownership out of the function. How do I get these two variables to return properly?


Solution

  • The error message here is misleading.

    It's talking about the type that BTreeMap holds, which is &(u8, u8) rather than (u8, u8) you promise Int the function signature. Since u8 is Copy, tuple (u8, u8) is also Copy, which means you can just deref n before inserting into the map and remove the type annotation from two_byte_set.

    use std::collections::BTreeSet;
    
    fn get_two_bytes(data: &[u8]) -> (Vec<(u8, u8)>, BTreeSet<(u8, u8)>) {
        let two_byte_vec = data.chunks(2).map(|x| (x[0], x[1])).collect::<Vec<_>>();
    
        let mut two_byte_set = BTreeSet::new();
        for &n in &two_byte_vec {
            two_byte_set.insert(n);
        }
    
        (two_byte_vec, two_byte_set);
    }