A reference to a value inside struct

How can I have a reference to a value inside a struct?
I tried to simplified my question as much as possible.

pub struct Point {
    x: i32,
    y: i32,
}

pub struct Screen<'a> {
    points: HashMap<i32, Point>,
    aliases: HashMap<&'a str, &'a Point>,
}

impl<'a> Screen<'a> {
    pub fn new() -> Screen<'a> {
        
        let p1 = Point{x:1, y:1};
        let p2 = Point{x:2, y:2};

        let mut points = HashMap::new();
        points.insert(1, p1);
        points.insert(2, p2);
        
        let mut aliases = HashMap::new();
        aliases.insert("p1", &p1); // 
        aliases.insert("p2", &p2);
        
        Screen {
            points: points,
            aliases: aliases,
        }
    }
}

error is:

error[E0382]: borrow of moved value: `p1`
  --> src/main.rs:25:30
   |
17 |         let p1 = Point{x:1, y:2};
   |             -- move occurs because `p1` has type `Point`, which does not implement the `Copy` trait
...
21 |         points.insert(1, p1);
   |                          -- value moved here
...
25 |         aliases.insert("p1", &p1);
   |                              ^^^ value borrowed here after move

Here is the playground for this code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d1c1d164a737cbf299ef8b5fa3ab1aa4

My question might be repeated, but unfortunately I couldn't find the answer by googling.

Don't put references in data structures unless you have enough an understanding of lifetimes and the borrow checker. References are not pointers, they are temporary compile time locks. By putting them in a data structure, you are saying that they point to something that strictly outlives them. But this isn't the case in your program.

When you have such small types as Point, just copy them around by deriving Copy. If the types start to get larger, you may consider using Rc or Arc to reduce the size, and give you cheap clones.

// right now

#[derive(Clone, Copy)]
struct Point {
    x: i32, y: i32
}

pub struct Screen<'a> {
    points: HashMap<i32, Point>,
    aliases: HashMap<&'a str, Point>,
}

// or if Point is large

pub struct Screen<'a> {
    points: HashMap<i32, Rc<Point>>,
    aliases: HashMap<&'a str, Rc<Point>>,
}
1 Like