How to print entire namespace in one statement?

I took the below code from this page:

fn main() {
   let mut test1 = Test::new("test1");
   println!("test1.a: {:?}", test1.a);
   println!("test1.b: {:?}", test1.b);
   println!();
   
   
   let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
   Test::init(test1_pin.as_mut());
   

   drop(test1_pin);
   println!("test1.a: {:?}", test1.a);
   println!("test1.b: {:?}", test1.b);
   println!();

   let mut test2 = Test::new("test2");
   println!("test1.a: {:?}", test1.a);
   println!("test1.b: {:?}", test1.b);
   println!("test2.a: {:?}", test2.a);
   println!("test2.b: {:?}", test2.b);
   println!();
   
   mem::swap(&mut test1, &mut test2);
   println!("test1.a: {:?}", test1.a);
   println!("test1.b: {:?}", test1.b);
   println!("test2.a: {:?}", test2.a);
   println!("test2.b: {:?}", test2.b);
   println!();
   
}







use std::pin::Pin;
use std::marker::PhantomPinned;
use std::mem;

#[derive(Debug)]
struct Test {
    a: String,
    b: *const String,
    _marker: PhantomPinned,
}


impl Test {
    fn new(txt: &str) -> Self {
        Test {
            a: String::from(txt),
            b: std::ptr::null(),
            // This makes our type `!Unpin`
            _marker: PhantomPinned,
        }
    }

    fn init<'a>(self: Pin<&'a mut Self>) {
        let self_ptr: *const String = &self.a;
        let this = unsafe { self.get_unchecked_mut() };
        this.b = self_ptr;
    }

    #[allow(unused)]
    fn a<'a>(self: Pin<&'a Self>) -> &'a str {
        &self.get_ref().a
    }

    #[allow(unused)]
    fn b<'a>(self: Pin<&'a Self>) -> &'a String {
        assert!(!self.b.is_null(), "Test::b called without Test::init being called first");
        unsafe { &*(self.b) }
    }
}

As you can see, I'm trying to analyze what's happening on each step in the code by using the println! macro. But it's kinda cumbersome to manually keep track on which variables are available in the namespace at the current location, and then manually write a println!-statement for each variable individually.

How can I refer to every item in the namespace simultaneously and then print it in a single statement?

Well, for one, it would be a lot shorter if you debug-printed the whole struct instead of always doing it field-by-field. You can also use the dbg!() macro to reduce formatting boilerplate: Playground

1 Like

wow that's awesome, thanks! Very helpful.

Is there a way to skip the prefix in the dbg! output? i.e. the line number and stuff in the bracket like this one:
[src/main.rs:15]

If you want more control over the formatting, you can always use println!("{test1:?}") instead of dbg!(&test1) to print just the test1 variable.

The default behaviour is really helpful when you are sprinkling dbg!() statements across your whole codebase or when there is control flow involved (i.e. you can't just go "the 4th item will always be on src/main.rs:15).

2 Likes