How to implement Copy trait for Box

use std::fmt::Debug;

pub struct SimpleLinkedList<T: Debug>(Option<Box<Node<T>>>);
 
 
struct Node<T: Debug> {
    data: T,
    next: Option<Box<Node<T>>>,
}



impl<T> SimpleLinkedList<T> where T: Debug {
    pub fn new() -> Self {
        SimpleLinkedList(None)
    }

    pub fn len(&self) -> usize {
        unimplemented!()
    }

    pub fn push(&mut self, _element: T) {
    
    
        let first_node = &mut self.0; 
        match first_node {
            None => {
                let new_node = Box::new(Node{data: _element, next: None});
                println!("This is the beginning");
                *first_node = Some(new_node);

            },
            Some(node) => {
                // let last_node = &mut node.next;

                let new_node = Box::new(Node{data: _element, next: Some(*node)});
                *first_node = Some(new_node);
            }
            
            
        }
    }

    pub fn pop(&mut self) -> Option<T> {
        unimplemented!()
    }

    pub fn peek(&self) -> Option<&T> {
        unimplemented!()
    }

    pub fn rev(self) -> SimpleLinkedList<T> {
        unimplemented!()
    }
    
    pub fn printlist(&self){
    
        let mut last_node = &self.0;
        loop {
            match last_node {
                
                Some(node) => {
                        println!("Value stored is {:?}", (*node).data);
                        last_node = &(node).next;

                }, 
                None => {
                    break
                }
                
            }
        }
        
        
    }
}

Fails with an error

   |
76 |                 let new_node = Box::new(Node{data: _element, next: Some(*node)});
   |                                                                         ^^^^^ move occurs because `*node` has type `std::boxed::Box<Node<T>>`, which does not implement the `Copy` trait

error: aborting due to previous error
1 Like

Use .clone() instead:

#[derive(Clone)]
struct Node<T: Debug> {
    data: T,
    next: Option<Box<Node<T>>>,
}

// ...
            Some(node) => {
                let new_node = Box::new(Node{data: _element, next: Some(node.clone())});
                *first_node = Some(new_node);
            }
// ...

Copy is only for types that can be memcpyd. Clone allows running arbitrary code, in this case allocating a new piece of memory to store the Node<T> of node.next in.

2 Likes

You can't implement Copy for Box, that would allow creation of multiple boxes referencing the same thing. The good news is that you don't need to in order to solve your problem.

The issue here is that you have a reference to the node inside the Some and you are trying to move the value out of it, which leaves a "gap" that invalidates self, which can quickly become unsafe. The solution is to replace the value in first_node with something to fill the gap, and since it is an Option, you can just use None. This is precisely what Option::take() provides for, so try matching on first_node.take() instead of first_node.

4 Likes

Obligatory reference to Introduction - Learning Rust With Entirely Too Many Linked Lists

Especially chapter 3 (An Ok Stack) will be very useful.

5 Likes

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.