我理解 Pin 的目的是防止值被移动。但为了正确使用
Pin::new_unchecked()
,需要做出很多承诺(例如“该值的数据不会被移动,也不会使其存储失效,直到它被删除”、DerefMut::deref_mut 和 Deref::deref指针类型 Ptr 应维护固定不变式,并且“引用 Ptr 取消引用将不会再次移出”另请参阅 https://doc.rust-lang.org/std/pin/struct.Pin.html#method .new_unchecked)。否则,编译器无法保证数据被固定。
既然调用者无论如何都需要做出上述承诺,为什么不直接使用 Pin 来做出承诺呢?除了语义标记之外,Pin 实际上还能带来什么好处?
Pin
是一种可强制执行的防止移动的合约。如果我创建一个 Box<MyType>
并声明 “MyType
是自引用且无法移动”,则编译器不会阻止用户执行 *my_type_box
并移动该值。使其成为 Pin<Box<MyType>>
实际上可以通过 &mut MyType
和 derefs 限制访问来确保不会发生这种情况。无论它是如何制作的,这都是Pin
的好处。
Pin::new_unchecked
是创建 Pin
包装器的 raw方式,但由于它对于任何
Deref
类型都是通用的,因此函数签名本身无法保证 Pin
合约的其余部分得到维护。文档中有一些示例说明了如何违反合同。因此它被标记为 unsafe
并要求用户提供这些保证。
但是,
Pin::new_unchecked
并不是创建Pin
-d值的唯一方法,实际上最常见且完全安全的方法是通过Box::pin
。 Box
可以自行做出此保证,因为其价值是拥有的且是唯一的。正如评论中所提到的,std::pin::pin!
是另一种为堆栈上的内容设置固定值的安全方法。
因此,没有什么会强迫您使用
Pin::new_unchecked
并给自己带来这些限制的负担。