一键导入
rust-pin
Pin and self-referential types expert covering Pin, Unpin, Future, async state machines, pinning projection, and memory stability guarantees.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Pin and self-referential types expert covering Pin, Unpin, Future, async state machines, pinning projection, and memory stability guarantees.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Actor model expert covering message passing, state isolation, supervision trees, deadlock prevention, fault tolerance, Actix framework, and Erlang-style concurrency patterns.
Rust anti-patterns and common mistakes expert. Handles code review issues with clone abuse, unwrap in production, String misuse, index loops, and refactoring guidance.
Advanced async patterns expert covering Stream implementation, zero-copy buffers, tokio::spawn lifetimes, plugin system scheduling, tonic streaming, and async lifetime management.
Advanced async patterns expert. Handles Stream processing, backpressure control, select/join operations, cancellation, Future trait implementation, and async runtime optimization.
Authentication and authorization expert covering JWT, API keys, OAuth, RBAC, password hashing, distributed token storage, and session management patterns.
Caching and distributed storage expert covering Redis, connection pools, TTL strategies, cache patterns (Cache-Aside, Write-Through), invalidation, and performance optimization.
| name | rust-pin |
| description | Pin and self-referential types expert covering Pin, Unpin, Future, async state machines, pinning projection, and memory stability guarantees. |
| metadata | {"triggers":["Pin","Unpin","self-referential","Future","async","Generator","pinning","memory stability"]} |
use std::pin::Pin;
use std::task::{Context, Poll};
use std::future::Future;
struct MyFuture {
state: State,
}
impl Future for MyFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// self is pinned, guaranteed not to move
let this = self.get_mut();
Poll::Ready(())
}
}
use std::pin::Pin;
struct Node {
value: i32,
// Self-reference: pointer to field within same struct
next: Option<Pin<Box<Node>>>,
}
use std::pin::Pin;
let future = async {
// async block creates a Future
};
// Pin future on heap
let pinned: Pin<Box<dyn Future<Output = ()>>> = Box::pin(future);
// Now safe to poll
use std::pin::Pin;
struct SelfReferential {
data: String,
ptr: *const String, // Points to data field
}
impl SelfReferential {
fn new(data: String) -> Pin<Box<Self>> {
let mut boxed = Box::new(SelfReferential {
data,
ptr: std::ptr::null(),
});
let ptr = &boxed.data as *const String;
boxed.ptr = ptr;
// SAFETY: boxed is on heap and won't move
unsafe { Pin::new_unchecked(boxed) }
}
fn data(&self) -> &str {
// SAFETY: ptr still valid because we're pinned
unsafe { &*self.ptr }
}
}
use std::pin::Pin;
struct Wrapper<T> {
inner: T,
extra: String,
}
impl<T: Unpin> Wrapper<T> {
// Safe projection: T is Unpin
fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
Pin::new(&mut self.get_mut().inner)
}
}
impl<T> Wrapper<T> {
// Unsafe projection: must maintain invariants
fn project_unchecked(self: Pin<&mut Self>) -> Pin<&mut T> {
// SAFETY: if Self is pinned, inner field is also pinned
unsafe {
Pin::new_unchecked(&mut self.get_unchecked_mut().inner)
}
}
}
use std::pin::Pin;
use futures::Future;
async fn process_data() {
let mut state = String::new();
// This reference is held across await
let state_ref = &mut state;
some_async_operation().await;
// state_ref must remain valid
state_ref.push_str("data");
}
// Compiler ensures state doesn't move by pinning the Future
| Type | Use Case | Example |
|---|---|---|
Pin<&T> | Borrowed, immutable | Pin<&Foo> |
Pin<&mut T> | Borrowed, mutable | Pin<&mut Foo> |
Pin<Box<T>> | Owned on heap | Pin<Box<Foo>> |
Pin<Arc<T>> | Shared ownership | Pin<Arc<Foo>> |
// Most types implement Unpin (safe to move)
struct MyType {
data: Vec<u8>,
}
// Unpin auto-implemented
// Which types DON'T implement Unpin?
// - Futures (from async/await)
// - Generators
// - Manually marked with PhantomPinned
use std::marker::PhantomPinned;
struct NotUnpin {
data: String,
_pin: PhantomPinned, // Opts out of Unpin
}
Need Pin when:
→ async/await (Future trait)
→ Self-referential struct
→ Implementing custom Future
→ Working with generators
Don't need Pin when:
→ Synchronous code
→ No self-references
→ Stack-allocated temporaries
→ Type is Unpin
Heap pinning:
→ Box::pin(value)
→ Safe, most common
Stack pinning:
→ pin!(value) // macro in std
→ More complex, zero allocation
Unsafe pinning:
→ Pin::new_unchecked()
→ Require SAFETY comments
Projecting to field:
→ If T: Unpin → Safe with Pin::new
→ If !Unpin → Unsafe, need Pin::new_unchecked
→ Use pin-project crate for safety
| Scenario | Need Pin? |
|---|---|
async {} block | ✅ Yes (Future) |
Box<dyn Future> | ✅ Yes |
| Self-referential struct | ✅ Yes |
| Regular Vec/HashMap | ❌ No |
| Stack variables | ❌ No |
| No self-references | ❌ No |
When working with Pin:
# Check if type is Unpin
cargo expand
# Verify async state machine
cargo expand --lib my_async_fn
# Test with miri
cargo +nightly miri test
Symptom: Compilation error about poll signature
// ❌ Bad: Future not pinned
fn poll_future(mut future: impl Future) {
future.poll(); // Error: no poll method
}
// ✅ Good: Pin the Future
fn poll_future(mut future: Pin<&mut impl Future>) {
future.as_mut().poll(cx); // OK
}
Symptom: Undefined behavior
// ❌ Bad: moving after pinning
let pinned = Box::pin(value);
let moved = *pinned; // Error: cannot move out of pinned
// ✅ Good: work with pinned reference
let pinned = Box::pin(value);
let pinned_ref: Pin<&mut Value> = pinned.as_mut();
Symptom: Unsoundness in self-referential types
// ❌ Bad: unsafe projection without guarantee
impl<T> Wrapper<T> {
fn bad_project(self: Pin<&mut Self>) -> &mut T {
&mut self.get_mut().inner // Unsound if T: !Unpin
}
}
// ✅ Good: safe projection with Unpin bound
impl<T: Unpin> Wrapper<T> {
fn safe_project(self: Pin<&mut Self>) -> Pin<&mut T> {
Pin::new(&mut self.get_mut().inner)
}
}