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?