在学习 Rust 中 Pin 的实现时,我感到很困惑。
我知道当一个类型不能安全移动时,它可以 impl !Unpin。Pin就是防止别人得到&mut T这些类型,让他们不能得到std::mem::swap。
如果 Pin 是为!Unpin类型设计的,为什么我们不能直接调用Pin::new这些类型呢?
它给出如下错误。我知道我应该使用 Pin::new_unchecked,但为什么呢?
struct TestNUnpin {
b: String,
}
impl !Unpin for TestNUnpin {}
// error: the trait `Unpin` is not implemented for `TestNUnpin`
std::pin::Pin::new(&TestNUnpin{b: "b".to_owned()});
Run Code Online (Sandbox Code Playgroud)
我的推理是:
我认为您要查找的内容可以在 的安全部分找到Pin::new_unchecked。本质上,Pin应该保证固定值永远不会再次移动(除非它实现Unpin),即使在被Pin删除之后也是如此。这种失败的一个例子是Pin<&mut T>。您可以删除Pin,并且该值不再被借用,因此您可以自由地再次移动它,从而破坏Pin的核心保证。这是一个例子:
use std::marker::PhantomPinned;
use std::pin::Pin;
fn main() {
let x = PhantomPinned;
{
let _pin = Pin::new(&x); // error[E0277]: `PhantomPinned` cannot be unpinned
}
let y = Box::new(x); // the PhantomPinned is moved here!
}
Run Code Online (Sandbox Code Playgroud)
如果不向借用检查器添加大量额外的复杂性,则此检查根本无法在编译时完成,因此它被标记为unsafe,本质上是说确保其工作是开发人员的工作。之所以Box::pin存在并且是安全的,是因为 的开发者Box可以保证它的安全:Box是一个拥有的、唯一的指针,所以一旦它Pin被删除,它的值也被删除,并且不再有任何方法可以移动该值。