0

In the following code, I cannot call hurr.set() even though I can access the individual fields in the struct. If you comment out the following code, then the code builds and runs.

    h1.set(100, 100);

Can someone help? Newbie to Rust here. I specifically don't want to make Hurr Copy because it would contain fields that are not copyable.

#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(unused_mut)]
use std::{ops::{DerefMut}, sync::{Arc,Mutex}};
use std::collections::HashMap;
use std::any::type_name;

#[derive(Debug)]
struct Hurr {
    width: u32,
    height: u32,
}
impl Hurr {
    fn new() -> Self {
        Hurr {
            width: 0,
            height: 0
        }
    }
    fn set(mut self, w:u32, h:u32) {
        self.width = w;
        self.height = h;
    }
}

fn type_of<T>(_: T) -> &'static str {
    type_name::<T>()
}

fn main() {

    let mut map : HashMap<String, Arc<Mutex<Hurr>>> = HashMap::new();
    
    let h = Arc::new(Mutex::new(Hurr::new()));
    map.insert("haha".to_string(), h);
    
    let mut h1 = map.get_mut("haha").unwrap().lock().unwrap();
    // this works!
    h1.width = 10;
    h1.height = 10;
    
    // the following fails to compile with
    // ^^ move occurs because value has type `Hurr`, which does not implement the `Copy` trait
    h1.set(100, 100);
    println!("h1: {:#?}, type_of(h1): {}", &h1, type_of(&h1));
 
}
Herohtar
  • 5,347
  • 4
  • 31
  • 41
Thingy
  • 171
  • 3
  • 2
    Change `mut self` to `&mut self`. Instead of taking `self` by reference in that method, you are consuming `self`, modifying it, and then dropping it, and you can't do that if `self` is in a `Arc`. – Aiden4 Jul 27 '21 at 00:45
  • You may take a look at https://stackoverflow.com/questions/59018413/when-to-use-self-self-mut-self-in-methods – hellow Jul 27 '21 at 08:32

1 Answers1

2

Let's examine why compiler thinks that your struct must be Copy:
fn set takes self by value, but the value you are attempting to consume is owned by a mutex. Therefore the only way for your code to compile is if the value is Copy.

Your code will compile if you take self by reference instead: fn set(&mut self, ..)

Ivan C
  • 1,772
  • 1
  • 8
  • 13