Move occurs when try to push Box<Node> in Vec

struct Node {
    	degree: usize,
    	connection:Option<Vec<Box<Node>>>,
    	value:Option<i32>,
    }

impl Default for Node{
	fn default() -> Node{
		let vec:Vec<Box<Node>> = Vec::new();
		Node{degree:0,connection:Some(vec),value:None}
	}
}

   impl Node{
     	pub fn connect_with(&mut self,node:Node){

	let heap_node = Box::new(node);
	self.connection.unwrap().push(heap_node);
	self.increment_degree();
}
pub fn increment_degree(&mut self){
	self.degree+=1;
}

pub fn decrement_degree(&mut self){
	if self.degree>0{
		self.degree-=1;
	}
}}

am getting error "move occurs because self.connection has type std::option::Option<std::vec::Vec<std::boxed::Box<eulerian::Node>>>, which does not implement the Copy trait
| help: consider borrowing the Option's content: self.connection.as_ref()"

at

self.connection.unwrap().push(heap_node);

But when I try to use self.connection.as_ref().unwrap().push(heap_node);
I get follwing error

cannot borrow data in a & reference as mutable

The mutable equivalent of Option::as_ref is Option::as_mut.

thank you

1 Like

Just a sidenote: you don't need a Box when you put the values in a Vec (if that's just because of the small example ignore this :slight_smile: )

2 Likes

@raidwas you are talking about this.. can you please explain little more about it

Practically you don't need type signature like Vec<Box<T>>. Actually, in Rust the Box<T> is not needed usually. The only practical case for many people that the Box<T> actually solve the problem is when they want to define recursive types like struct Node<T>(T, Option<Box<Node<T>>>).

1 Like

Can you give me some online example so that I can get to know what recursive types you mean here.

So this example using Box https://exercism.io/tracks/rust/exercises/simple-linked-list/solutions/c4b7679eec0d4602859497dac2c26f31 ..so I can say this right way.

Linked lists and trees are the most common examples of recursive type. For the linked list part, there's an awesome article called Learn Rust With Entirely Too Many Linked Lists.

1 Like

@Hyeonu thank you

@Hyeonu I read this reddit post https://www.reddit.com/r/rust/comments/8kujd1/newbie_correct_way_to_pass_vector_of_references/
I want to achieve same thing ..have vector of references ..I just want to ask ...cannot it be done using Box instead of using lifetime to node?

@ninja0x0 you may read more about smart pointers.

According to the Rust Book, Vec and Box are both smart pointers (https://doc.rust-lang.org/book/ch15-00-smart-pointers.html).

They implement special behaviour to referencing, as memory management is done by ownership. More examples of smart pointers you might be interested are Rc (to provide multiple references to the same object) and Refcell (to provide inner mutability). Composition of smart pointers is possible and eventually necessary, but not all of them are.

Collections (https://doc.rust-lang.org/std/collections) like Vec which you might be interested in and are useful are HashSet, HashMap, LinkedList.

1 Like

I read about smart pointers.I will look into collections implementations.But can you tell me what is proper implementation of my small snippet code which I posted above.

@ninja0x0 Well, I'm in no position greater than anybody here to say what is proper or not. Much probably, someone can answer you with more property if I miss something. :sweat_smile:

What I understand from the snippet you've provided is that you want a Node to reference as many nodes the user needs. And it is implicit that a Node may be referenced according to the user's will as well.

The std::rc::Rc is required, which will allow us to have any node to be pointed by as many nodes as we want.

Also, for a Node to point to more than one node, we need some Collection. To avoid unnecessary complications, we may use the most common and standard Vec.

use std::rc::Rc;

struct Node {
    degree: usize,
    connection: Vec<Rc<Node>>,
    value: Option<i32>,
}

impl Default for Node {
    fn default() -> Node {
        Node {
            degree: 0,
            connection: Vec::new(),
            value: None,
        }
    }
}

impl Node {
    pub fn connect_with(&mut self, node: &Rc<Node>) {
        self.connection.push(Rc::clone(node));
        self.increment_degree();
    }
    pub fn increment_degree(&mut self) {
        self.degree += 1;
    }

    pub fn decrement_degree(&mut self) {
        if self.degree > 0 {
            self.degree -= 1;
        }
    }
}

fn main() {
    // Creating Nodes
    let root = Rc::new(Node::default());
    let n1 = Rc::new(Node::default());
    let n2 = Rc::new(Node::default());
    let n3 = Rc::new(Node::default());

    // Making connectiion between nodes
    root.connect_with(&n1);
    root.connect_with(&n2);
    root.connect_with(&n3);
    n1.connect_with(&n2);
    n1.connect_with(&n3);
    n2.connect_with(&n3);
    n3.connect_with(&root);
}
1 Like

The RefCell is not necessary to implement interior mutability, in this case, since Vec already provides it.

Someone may confirm it. I believe I've read it somewhere else.

1 Like

Thank you so much for your solution.I appreciate your time @nlsn

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.