为什么 Pin::new_unchecked(&self) 有效但 Pin::new_unchecked(&self).as_ref() 无效?

Why Pin::new_unchecked(&self) worked but not Pin::new_unchecked(&self).as_ref()?

我正在编写一个 StackBox,它引用在内存映射堆栈上分配的变量并实现 Drop 特征,以便 StackBox 可以用作参考。

因为我可以保证如果 StackBox 曾经被我的代码创建过,那么内存映射堆栈一定不会被修改,所以我决定添加 pin 方法 returns Pin<&T>.

但是我发现 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>

但事实并非如此。它实际上是从 return 类型推导出函数调用的类型,所以你正在调用 Pin::<&T>::new_unchecked() 而它是 self 在这个调用中转换为 &T ,通过使用下面的 deref() 实现。就好像:

    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>> 开头(这没有多大意义),则无需进行任何转换。