直接回答:Pin 承诺一个值在内存中的地址不再移动。这个承诺对普通类型无所谓,但对自引用结构是生死攸关的:结构体字段里存着指向自身另一字段的指针,一旦整体 move,指针就变成悬垂。Rust 的类型系统不表达自引用,它主要出现在编译器生成的 async 状态机里——跨 await 的局部变量可能持有对彼此的引用。Pin 用一个零成本的类型标记把这个"不许动"的契约立起来。
展开解析:Unpin 是个 auto trait,绝大多数类型自动实现,含义是"我被移动也无所谓"——对它们 Pin 不产生任何约束,可以随意取走内部值。只有显式 impl !Unpin 的类型(如 async 块生成的 Future)才受 Pin 约束:一旦钉住,safe 代码无法再 move 它,也没有安全途径拿到 &mut T。配套设计:Box::pin 把值放进堆上固定地址再钉住;pin_project 处理结构体部分字段钉住、部分不钉的投影。理解 Pin 是理解 poll 签名 fn poll(self: Pin<&mut Self>, ...) 的钥匙——executor 必须钉住 Future 才能安全地驱动状态机。
追问方向:Unpin 为什么是 auto trait 而非手动实现?栈上 pin(pin!)如何阻止移动?PhantomPinned 起什么作用?
(约 440 字)