为什么 Pin::new_unchecked(&self) 工作,但 Pin::new_unchecked(&self).as_ref()?



我正在编写一个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 }                 
}                                             
}                                                 

当你写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()impl,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>>开始(这没有太大意义(,则不需要进行转换。

相关内容

  • 没有找到相关文章

最新更新