我正在编写一个引用内存映射堆栈上分配的变量的StackBox,并实现了Drop特征,以便可以将StackBox用作引用。
因为我可以保证如果StackBox是由我的代码创建的,那么内存映射堆栈一定不能被修改,所以我决定添加返回Pin<&T>的pin方法。
然而,我发现奇怪的是,Pin::new_unchecked(&self)可以工作,但Pin::new_unchecked(&self).as_ref()不能工作。
下面是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 }
}
} 发布于 2021-06-16 23:36:28
当您编写Pin::new_unchecked(&self)时,您可能指的是Pin::new_unchecked(self),因为self已经是一个引用,但分析基本上是相同的:
pub fn pin(&self) -> Pin<&T> {
unsafe { Pin::new_unchecked(self) }
}您可能在想,您正在创建一个Pin<&StackBox<T>>,然后它会神奇地转换为一个Pin<&T>。
但这并不是真正发生的事情。它实际上是从返回类型推导出函数调用的类型,所以您调用的是Pin::<&T>::new_unchecked(),在此调用中,通过使用下面实现的deref(),self被转换为&T。这就好像是:
pub fn pin(&self) -> Pin<&T> {
unsafe { Pin::<&T>::new_unchecked(self.deref()) }
} 这可以更明显地写成:
pub fn pin(&self) -> Pin<&T> {
unsafe { Pin::new_unchecked(&*self.ptr) }
} 至于为什么带有as_ref()的版本不能工作,这是因为您的self是&StackBox<T>,而不是StackBox<T>。例如,as_ref()对于移除智能指针层很有用,因此它可以将Pin<Box<T>>转换为Pin<&T>。但如果您从Pin<&Box<T>>开始(这没有太多意义),就不需要进行转换。
https://stackoverflow.com/questions/68001056
复制相似问题