Debug Trait on Generic type

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



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

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

I obviously cant do that because Node doesn't have Debug trait implemented for it. I cant do it by just using #[derive(Debug)] because Node is not defined on the primitive type but on Generic type.

Please help me understand how can I solve this problem.

Of course you can derive Debug on Node. It will be active only if T: Debug, but if this is not the case you probably won't be able to do anything useful in the hand-written implementation anyway.

If you want to be able to print the data inside the linked list, then you will need to enforce that it implements Debug:

use std::fmt::Debug;

pub struct SimpleLinkedList<T>(Option<Box<Node<T>>>);

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

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

impl<T> SimpleLinkedList<T>
where
    T: Debug,
{
    pub fn printlist(&self) {
        let last_node = self.0;
        loop {
            match last_node {
                Some(node) => {
                    println!("Value stored is {:?}", (*node).data);
                    last_node = (node).next;
                }
                None => break,
            }
        }
    }
}

Note that the constraint is only declared on the second impl block in this case - this means that instances of Node and SimpleLinkedList that contain non-Debug data can exist, you just can't use the printlist method on them. If you wanted to enforce that all instances contain Debug data, then you would need to put a similar constraint on the type definitions as well.

1 Like

Thanks a lot, Could you please help with implementing Debug on Type definitions also.

That would look like this:

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 printlist(&self) {
        let last_node = self.0;
        loop {
            match last_node {
                Some(node) => {
                    println!("Value stored is {:?}", (*node).data);
                    last_node = (node).next;
                }
                None => break,
            }
        }
    }
}

The differences being:

  • Debug bounds have been added to the type definitions.
  • All methods must be in an impl block that constrains T to be Debug (because otherwise you'd be saying that any T can be used for those methods, which conflicts with the constraints on the type itself).
1 Like

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