Search code examples
rustrust-cargoi3

Rust E0382 - value used here after move


I am new to Rust and is really struggling with way to write code the Rust way. I understand its rules to enforce memory correctness, however I cannot figure out the changes required to comply in code.

I have created a Tree like object from the json structure recieved from the application.

I am trying to create two operations on tree,

  1. Get the leaves of tree
  2. Get the mapping of parent -> children in a map

The high level code looks like this

fn rename_workspaces(conn: Connection) {
    let i3_info = I3Info::new(conn);

    let _leaves = i3_info.get_leaves();
    let _parent_child = i3_info.dfs_parent_child();
}

However, rust is complaining that i3_info variable has been used after the move. I understand its complaint, however, I cannot figure out what should be the correct Rust way to solve it.

Please help me to figure out the change in thinking required to solve this. This is important, because my application really need to perform these calculations on the tree structure multiple times.

Interesting thing is , I am not really mutating the structure, just iterating over it and returning the new / mutated structure from the function.

Source link: https://github.com/madhur/i3-auto-workspace-icons-rust/blob/main/src/main.rs


Solution

  • The problem is that you have declared the methods of I3Info such that they consume (move) the I3Info:

       pub fn dfs_parent_child(self) ...
       pub fn get_leaves(self) ...
    

    To not consume the I3Info, allowing it to be used more than once, declare your methods to take references to the I3Info:

       pub fn dfs_parent_child(&self) ...
       pub fn get_leaves(&self) ...
    

    You will need to modify the code within these methods, also, to work with references because this change also means you can no longer move things out of self — they have to be left intact. Sometimes this is as simple as putting & before a field access (&self.foo instead of self.foo), and sometimes it will require more extensive changes.


    The general “Rust way of thinking” lessons here are:

    1. Think about the type of your method receivers. self is not always right, and neither is &self.

    2. Don't take ownership of values except when it makes sense. Passing by & reference is a good default choice (except for Copy types, like numbers).