结论:Pin<P> 是一个承诺"被指向的数据不再移动内存地址"的指针包装。自引用结构(字段持有指向自身另一字段的引用)一旦移动,内部指针就会悬垂;Rust 的类型系统无法表达这种结构,所以约定:把数据 Pin 住之后才能构造自引用,移动被禁止,安全得以维持。它是 async/await 的基石——编译器把 async 块编译成的状态机 future 就是自引用的。

展开:为什么 Future 会自引用:async 块里跨 .await 存活的局部变量被存进状态机结构体,变量间的借用变成结构体内部的自引用;执行器每次 poll 后 future 可能被移动,若没有 Pin 约束,这些内部引用全部失效。关键 API:Pin::new 只接受指向 Unpin 类型的指针(大多数类型是 Unpin,移动它们无所谓);!Unpin 类型(如生成的 future)要用 Box::pinpin_mut! 钉住,之后只能拿到 Pin<&mut T>,无法再安全地移出。易错点:Pin 保证的是"不移动"而非"不可变";栈上 pin 住的对象不能用 mem::swap 交换,那等于变相移动。

use std::pin::Pin;
use std::marker::PhantomPinned;
struct SelfRef {
    data: String,
    ptr: *const String, // 指向自身 data
    _pin: PhantomPinned, // 标记 !Unpin
}
// 使用方必须 Box::pin 后才能安全地初始化 ptr

追问方向:PhantomPinned 的作用、Pin 的投影(pin projection)为什么需要 pin-project 宏。