I was writing a StackBox that references a variable allocated on a memory-mapped stack and implemented Drop trait so that StackBox can be used as a reference.
Since I can guarantee that if StackBox is ever created by my code, then the memory-mapped stack must not be modified, I decided to add pin method that returns Pin<&T>.
However I found it weird that Pin::new_unchecked(&self) worked but Pin::new_unchecked(&self).as_ref() doesn't work.
Here's the full code of StackBox:
pub struct StackBox<'a, T> {
ptr: *mut T,
phantom: PhantomData<&'a T>,
}
impl<'a, T> StackBox<'a, T> {
fn new(ptr: *mut T) -> StackBox<'a, T> {
StackBox {
ptr,
phantom: PhantomData
}
}
/// Why does this compile?
/// Pin::new_unchecked(&self).as_ref() doesn't work here
pub fn pin(&self) -> Pin<&T> {
unsafe { Pin::new_unchecked(&self) }
}
}
impl<'a, T> Drop for StackBox<'a, T> {
fn drop(&mut self) {
unsafe {
self.ptr.drop_in_place();
}
}
}
impl<'a, T> Deref for StackBox<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { & *self.ptr }
}
}
impl<'a, T> DerefMut for StackBox<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.ptr }
}
}
When you are writing
Pin::new_unchecked(&self)you probably meanPin::new_unchecked(self)becauseselfis already a reference, but the analysis is basically the same:You are probably thinking that you are creating a
Pin<&StackBox<T>>and then it magically gets converted into aPin<&T>.But that is not really what it is happening. It is actually deducing the type of the function call from the return type, so you are calling
Pin::<&T>::new_unchecked()and it is theselfthat is converted into a&Tin this call, by using thederef()impl from below. It is as if:This can be written more obviously as:
As to why the version with
as_ref()does not work, this is because yourselfis a&StackBox<T>, not aStackBox<T>.as_ref()is useful to remove a smart-pointer layer, so it can convert aPin<Box<T>>into aPin<&T>, for example. But if you start with aPin<&Box<T>>(that doesn't make too much sense), there is no conversion to be done.