Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does moving the string variable give error here?

Tags:

rust

use std::collections::HashMap;
#[derive(Clone,Debug)]
pub enum Address {
    Ptr(Box<Node>),
    None,
}

#[derive(Clone,Debug)]
pub struct Node {
    connection: String,
    value: i32,
    next: Address,
}

impl Node {

    pub fn new(connection:String, value: i32) -> Node{
        Node{
            connection,
            value,
            next: Address::None,
        }
    }

    pub fn insert(&mut self, connection: String, value: i32) {
        match self.next {
            Address::Ptr(ref mut v) => {
                v.insert(connection,value);
            }
            Address::None => {
                self.next = Address::Ptr(Box::new(Node{connection,value,next:Address::None}))
            }
        }
    }
    
}


struct GraphAdj {
    vec_edge: HashMap<String,Node>
}

impl GraphAdj {
    pub fn new() -> GraphAdj{
        GraphAdj{
            vec_edge: HashMap::new(),
        }
    }

    pub fn insert(&mut self, value: String) -> Result<(),String> {

        if self.vec_edge.contains_key(&value) {
            return Err(format!("Key already present"))
        }

        self.vec_edge.insert(value,
            Node::new(String::from(""),-1)
        );
        Ok(())
    } 

    pub fn add_connection(&mut self, 
        source_vertex: String,
        destination_vertex: String,
        cost: i32,
    ){

        for (key,value) in self.vec_edge.iter_mut() {
            if *key == source_vertex {
                value.insert(destination_vertex,cost);
            } 
        }
    }

}
fn main(){}

I get the following error

***cargo check
    Checking rust_graph v0.1.0 (D:\projects\DSA\graph\rust_graph)
error[E0382]: use of moved value: `destination_vertex`
  --> src\main.rs:36:30
   |
30 |         destination_vertex: String,
   |         ------------------ move occurs because `destination_vertex` has type `String`, which does not implement the `Copy` trait
...
36 |                 value.insert(destination_vertex,cost);
   |                              ^^^^^^^^^^^^^^^^^^ value moved here, in previous iteration of loop
error: aborting due to previous error***

***For more information about this error, try `rustc --explain E0382`.
error: could not compile `rust_graph`
To learn more, run the command again with --verbose.***

I get that the String variable is moved, but why is it an issue here? I mean i am not using it afterwards anyway.

like image 657
Nishan Maharjan Avatar asked Jul 18 '26 00:07

Nishan Maharjan


1 Answers

This is the function where the error occurs:

   pub fn add_connection(
        &mut self,
        source_vertex: String,
        destination_vertex: String,
        cost: i32,
    )
    {
        for (key, value) in self.vec_edge.iter_mut() {
            if *key == source_vertex {
                value.insert(destination_vertex, cost);
            }
        }
    }

And here is the definition of insert() where we get the error:

pub fn insert(&mut self, connection: String, value: i32)

So you have a String instance which you try to move multiple times, by passing it as argument to insert(). Each invocation of the loop will move the string, and after you move it once, you will not be able to move it again.

The compiler has no way of knowing how many iterations this loop will have or how many times the condition *key == source_vertex will evaluate to true, so it assumes that it may happen multiple times.

In order to resolve the error you either have to clone() the string and move (pass as argument) the clone:

  for (key, value) in self.vec_edge.iter_mut() {
       if *key == source_vertex {
           value.insert(destination_vertex.clone(), cost);
       }
  }

or break from the loop once the value has been moved:

for (key, value) in self.vec_edge.iter_mut() {
    if *key == source_vertex {
       value.insert(destination_vertex, cost);
       return; // or break; -> exit from the loop or method
    }
}
like image 170
Svetlin Zarev Avatar answered Jul 19 '26 20:07

Svetlin Zarev