Search code examples
referencerustcloneownership

Is there any way to clone a reference type into an owned type?


I have a method that I want to return an owned copy of an element. I can justify why I want this if needed.

Here is a minimal reproducible example: (playground)

use std::collections::HashMap;

struct AsciiDisplayPixel {
    value: char,
    color: u32,
}

struct PieceToPixelMapper {
    map: HashMap<usize, AsciiDisplayPixel>,
}

impl PieceToPixelMapper {
    pub fn map(&self, index: usize) -> Option<AsciiDisplayPixel> {
        let pixel = self.map.get(&index);
        let pixel = match pixel {
            None => return None,
            Some(x) => x,
        };

        return Some(pixel.clone());
    }
}

fn main() {
    println!("Hello World");
}

This fails to compile with

error[E0308]: mismatched types
  --> src/main.rs:20:21
   |
20 |         return Some(pixel.clone());
   |                     ^^^^^^^^^^^^^ expected struct `AsciiDisplayPixel`, found reference
   |
   = note: expected type `AsciiDisplayPixel`
              found type `&AsciiDisplayPixel`

I'm not sure why this is the case. According to the documentation on clone, it looks like the resulting type of clone be whatever the parent was, so if you clone a reference, you still get a reference, which I guess if fine, but then I have no clue how I clone to owned data. to_owned seems to have the exact same problem and gives the same error message.


Solution

  • AsciiDisplayPixel needs to implement Clone for you to be able to clone (Copy, Debug, and others probably make sense too):

    #[derive(Clone)]
    struct AsciiDisplayPixel {
        value: char,
        color: u32,
    }
    

    (updated playground)

    at which point the implementation can be simplified to:

    pub fn map(&self, index: usize) -> Option<AsciiDisplayPixel> {
        self.map.get(&index).cloned()
    }