用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill rust-type-system命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
正在显示 SKILL.md
| name | rust-type-system |
| description | | Use when this capability is needed. |
Make invalid states unrepresentable. If the compiler can catch it, don't leave it to runtime.
Before reaching for if checks or runtime panics:
Wrap primitives to create distinct, incompatible types:
// Without newtypes: easy to swap arguments
fn transfer(from: u64, to: u64, amount: u64) { ... }
transfer(order_id, user_id, cents); // Compiles! Bug at runtime.
// With newtypes: compiler catches swaps
struct UserId(u64);
struct OrderId(u64);
struct Cents(u64);
fn transfer(from: UserId, to: UserId, amount: Cents) { ... }
transfer(order_id, user_id, amount); // E0308: mismatched types ✓
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Email(String);
impl Email {
pub fn new(s: &str) -> Result<Self, EmailError> {
// Validate ONCE at the boundary
if s.contains('@') && s.split('@').nth(1).map_or(false, |d| d.contains('.')) {
Ok(Email(s.to_lowercase()))
} else {
Err(EmailError::Invalid(s.to_string()))
}
}
pub fn as_str(&self) -> &str { &self.0 }
}
// Deref for ergonomic access to String methods
impl std::ops::Deref for Email {
type Target = str;
fn (&) & { &. }
}
(to: &Email, body: &) { }
pub struct NonEmpty<T> {
head: T,
tail: Vec<T>,
}
impl<T> NonEmpty<T> {
pub fn new(head: T) -> Self { Self { head, tail: vec![] } }
pub fn push(&mut self, item: T) { self.tail.push(item); }
// Infallible — always returns something (unlike Vec::first())
pub fn first(&self) -> &T { &self.head }
pub fn len(&self) -> usize { 1 + self.tail.len() }
}
Encode state transitions in the type system. Invalid transitions don't compile.
// State marker types (zero-sized, no runtime cost)
struct Draft;
struct PendingReview;
struct Published;
struct Post<State> {
content: String,
_state: std::marker::PhantomData<State>,
}
// Only Draft posts can be edited
impl Post<Draft> {
pub fn new(content: String) -> Self {
Self { content, _state: std::marker::PhantomData }
}
pub fn edit(&mut self, content: String) {
self.content = content;
}
pub fn submit(self) -> Post<PendingReview> {
Post { content: self.content, _state: std::marker::PhantomData }
}
}
// Only PendingReview posts can be published or rejected
impl Post<PendingReview> {
pub fn approve(self) -> Post<Published> {
Post { content: self.content, _state: std::marker::PhantomData }
}
pub fn reject(self) -> Post<Draft> {
Post { content: .content, _state: std::marker::PhantomData }
}
}
<Published> {
(&) & { &.content }
}
= Post::(.());
post.(.());
= post.();
= post.();
(, post.());
// Marker types for builder state
struct NoUrl;
struct HasUrl(String);
struct NoMethod;
struct HasMethod(Method);
struct RequestBuilder<U, M> {
url: U,
method: M,
headers: Vec<(String, String)>,
timeout_secs: u64,
}
// Start with no required fields set
impl RequestBuilder<NoUrl, NoMethod> {
pub fn new() -> Self {
Self { url: NoUrl, method: NoMethod, headers: vec![], timeout_secs: 30 }
}
}
// Set URL — transitions to HasUrl state
impl<M> RequestBuilder<NoUrl, M> {
pub fn url(self, url: impl Into<String>) -> RequestBuilder<HasUrl, M> {
RequestBuilder { url: HasUrl(url.into()), method: self.method,
headers: self.headers, timeout_secs: self.timeout_secs }
}
}
// Set method — transitions to HasMethod state
impl<U> RequestBuilder<U, NoMethod> {
pub fn method(, method: Method) RequestBuilder<U, HasMethod> {
RequestBuilder { url: .url, method: (method),
headers: .headers, timeout_secs: .timeout_secs }
}
}
<U, M> RequestBuilder<U, M> {
( , key: <>, val: <>) {
.headers.((key.(), val.()));
}
( , secs: ) {
.timeout_secs = secs;
}
}
<HasUrl, HasMethod> {
() Request {
Request { url: .url., method: .method.,
headers: .headers, timeout_secs: .timeout_secs }
}
}
= RequestBuilder::()
.()
.(Method::GET)
.(, )
.();
For runtime state (when typestate is too rigid):
#[derive(Debug)]
pub enum Connection {
Disconnected,
Connecting { attempt: u32, started_at: std::time::Instant },
Connected { session_id: String, established_at: std::time::Instant },
Reconnecting { attempts: u32, last_error: String },
}
impl Connection {
pub fn connect(&self) -> Result<Connection, ConnectError> {
match self {
Connection::Disconnected => Ok(Connection::Connecting {
attempt: 1,
started_at: std::time::Instant::now(),
}),
Connection::Connected { .. } => Err(ConnectError::AlreadyConnected),
other => Err(ConnectError::InvalidState(format!("{other:?}"))),
}
}
pub fn is_usable(&self) -> bool {
matches!(self, Connection::Connected { .. })
}
}
// Make illegal transitions explicit in code:
// You cannot call send() on a Disconnected connection
// because send() takes &Connection and does the state check.
PhantomData<T> adds type information without runtime cost:
use std::marker::PhantomData;
// Token that is valid only for a specific user's session
struct Token<User> {
value: String,
_user: PhantomData<User>, // Zero bytes at runtime
}
struct AdminUser;
struct RegularUser;
fn admin_action(token: &Token<AdminUser>) { /* only admins */ }
// Token<RegularUser> cannot be passed to admin_action
// The types are distinct even though the struct is the same.
Prevent external implementations — stable extension point without full openness:
mod private {
pub trait Sealed {} // Private, so external crates can't implement it
}
pub trait DatabaseDriver: private::Sealed {
fn execute(&self, query: &str) -> Result<Rows, DbError>;
}
// Only types in this crate implement Sealed (and thus DatabaseDriver)
pub struct PostgresDriver { /* ... */ }
impl private::Sealed for PostgresDriver {}
impl DatabaseDriver for PostgresDriver { /* ... */ }
// External code can USE DatabaseDriver but not implement it
Allow adding variants without breaking downstream:
#[non_exhaustive]
pub enum Event {
Click { x: i32, y: i32 },
KeyPress(char),
Resize { width: u32, height: u32 },
// Future variants won't break the API
}
// External match MUST have _ arm:
match event {
Event::Click { x, y } => handle_click(x, y),
Event::KeyPress(c) => handle_key(c),
Event::Resize { width, height } => handle_resize(width, height),
_ => {} // Required: future variants
}
For newtypes that need identical memory layout to the wrapped type (FFI, safety):
#[repr(transparent)]
pub struct NonZeroU32(u32);
// Same size and alignment as u32 — safe to transmute
// Useful for: FFI safety, optimization, zero-overhead wrappers
!)Use the never type ! to indicate computations that diverge (i.e. never return). It can be coerced to any other type.
fn loop_forever() -> ! {
loop {
// never returns
}
}
Use std::marker::PhantomData to tell the compiler that a struct behaves as if it owns a value of type T even if it only uses it at compile time (e.g. for lifetime bounds or variance assertions).
use std::marker::PhantomData;
pub struct Serializer<T> {
format: String,
_marker: PhantomData<T>, // type-level association
}
impl<T> Serializer<T> {
pub fn new(format: String) -> Self {
Self {
format,
_marker: PhantomData,
}
}
}
| Need | Pattern |
|---|---|
| Prevent ID swaps | Newtype |
| Validate at boundary | Newtype + new() returning Result |
| Required builder fields | Typestate Builder |
| State machine (compile-time) | Typestate with PhantomData |
| State machine (runtime) | Enum with transitions |
| Prevent external trait impl | Sealed Trait |
| Future-proof enum | #[non_exhaustive] |
| Generic type info, no data | PhantomData |
// Bad: boolean flags allow invalid combinations and unclear call sites.
fn connect(use_tls: bool, verify_cert: bool) {}
connect(false, true);
// Good: encode modes as named variants.
enum TlsMode { Disabled, InsecureForLocalDev, Verified }
fn connect(tls: TlsMode) {}
// Bad: public raw IDs are easy to swap.
fn load(user_id: u64, order_id: u64) {}
// Good: newtypes prevent accidental cross-domain use.
struct UserId(u64);
struct OrderId(u64);
fn load(user_id: UserId, order_id: OrderId) {}
Source: adxptived/Rust-Skills — distributed by TomeVault.