I am trying to create a smart pointer type that is copiable and allows obtaining a temporary mutable reference to the pointee. For example:
use std::ptr::NonNull;
use std::marker::PhantomData;
#[derive(Clone, Copy)]
pub struct MyPointer<'a, T> {
ptr: NonNull<T>,
_phantom: PhantomData<&'a T>,
}
pub struct Foo { v: Vec<i32> }
impl Foo {
pub fn with_callback(&mut self, f: impl for<'a> FnOnce(MyPointer<'a, Foo>)) {
f(MyPointer { ptr: NonNull::from(&mut *self), _phantom: PhantomData });
}
}
impl<'a> MyPointer<'a, Foo> {
pub fn do_something_mut(&self, x: i32) {
// SAFETY: All methods on `MyPointer` and `T` are non-reentrant,
// and never create references lasting longer than the method body.
let inner: &'a mut Foo = unsafe { &mut *self.ptr.as_ptr() };
(*inner).v.push(x);
}
}
Ideally, a user can safely write something like foo.with_callback(|x| { x.do_something_mut(1); x.do_something_mut(2); })
.
My question is, what is the correct thing to put inside PhantomData
? And just to double check, it shouldn't be necessary to use UnsafeCell
?