Ref mut vs &mut convention

self.0 is a HashMap, meaning that remove returns an Optional:

        if let Some(camera) = &mut self.0.remove(&camera_port) {
            camera.kill_videocapture_process();
        }

I want to mutate that optional (fn kill_videocapture_process(&mut self)). Is it the convention to write the code above or use what I think is equivalent?

        if let Some(ref mut camera) = self.0.remove(&camera_port) {
            camera.kill_videocapture_process();
        }

Are there any differences between the two?

They are completely equivalent. The ref mut is less well known. However, in this case I would write neither; I would write

if let Some(mut camera) = self.0.remove(&camera_port) {
    camera.kill_videocapture_process();
}

Since the camera is being removed and dropped there is no reason to avoid moving it, and method dispatch will take care of implicitly adding the needed &mut.

Also, have you considered putting this operation in impl Drop for Camera instead? It is generally good to ensure that things are cleaned up on drop; it makes your program less likely to accidentally leak resources.

5 Likes

Implementing the drop trait sounds like a good (and safer) idea, though I have never done that before in Rust. Since this method only "drops" (as in cleans up/kills some process) one of the items from a struct (the others are a usize and a String), do I have to do anything further in the drop method to drop those?

The Drop::drop method is part of the destructor of your type and runs just before Rust drops the various members of your type. Thus, the following code outputs "3121":

struct One;

impl Drop for One {
    fn drop(&mut self) {
       print!("1");
    }
}

struct Two {
    one: One
}

impl Drop for Two {
    fn drop(&mut self) {
       print!("2");
    }
}

struct Three {
    one: One,
    two: Two,
}

impl Drop for Three {
    fn drop(&mut self) {
       print!("3");
    }
}

fn main() {
    let _t: Three = Three { one: One, two: Two { one: One } };
    println!();
}

By swapping the order of items in struct Three, you can change the output to "3211", but you'd have to use ManuallyDrop or clever tricks to stop the compiler generating code to run the drop impls for each of the items.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.