mcpField
M
m04-zero-cost

m04-zero-cost

github.com/actionbook开发1.6k3.4k 次安装9 周前更新
代码仓库

关于 m04-zero-cost

m04-zero-cost 是帮助 Rust 开发者选择类型抽象方式的学习技能。它从分派、性能和编译时间等权衡比较泛型、Trait 对象与枚举。

主要功能

  1. 01选择抽象层级的提示
  2. 02静态与动态分派比较
  3. 03泛型、Trait 对象和枚举指南
  4. 04对象安全检查
  5. 05Rust 错误代码指南

适用场景

  1. 01为性能敏感代码选择分派方式
  2. 02设计异构集合
  3. 03评估插件架构中的类型方案

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/actionbook/rust-skills --skill m04-zero-cost

安装后在 Claude Code 中输入/m04-zero-cost确认已加载。

详细介绍

零成本抽象

第 1 层:语言机制

核心问题

我们需要编译时多态还是运行时多态?

在选择泛型和 trait 对象之前:

  • 类型在编译时已知吗?
  • 是否需要异构集合?
  • 性能优先级是什么?

错误 → 设计问题

错误别只说不妨问问
E0277“添加 trait 约束”这个抽象处于合适的层级吗?
E0308“修正类型”应该统一类型还是保持类型不同?
E0599“导入 trait”这个 trait 是合适的抽象吗?
E0038“使其满足对象安全”我们真的需要动态分发吗?

思考提示

添加 trait 约束之前:

  1. 需要什么抽象?

    • 行为相同,类型不同 → trait
    • 行为不同,类型相同 → enum
    • 不需要抽象 → 具体类型
  2. 何时才能确定类型?

    • 编译时 → 泛型(静态分发)
    • 运行时 → trait 对象(动态分发)
  3. 优先考虑哪些权衡?

    • 性能 → 泛型
    • 编译时间 → trait 对象
    • 灵活性 → 视情况而定

向上追溯 ↑

类型系统阻碍开发时:

E0277 (trait bound not satisfied)
    ↑ Ask: Is the abstraction level correct?
    ↑ Check: m09-domain (what behavior is being abstracted?)
    ↑ Check: m05-type-driven (should use newtype?)
持续出现的错误追溯到问题
复杂的 trait 约束m09-domain抽象合适吗?
对象安全问题m05-type-driven类型状态能帮上忙吗?
类型爆炸m10-performance能接受 dyn 的开销吗?

向下追溯 ↓

从设计到实现:

"Need to abstract over types with same behavior"
    ↓ Types known at compile time → impl Trait or generics
    ↓ Types determined at runtime → dyn Trait

"Need collection of different types"
    ↓ Closed set → enum
    ↓ Open set → Vec<Box<dyn Trait>>

"Need to return different types"
    ↓ Same type → impl Trait
    ↓ Different types → Box<dyn Trait>

快速参考

模式分发方式代码体积运行时开销
fn foo<T: Trait>()静态+膨胀零
fn foo(x: &dyn Trait)动态最小vtable 查找
impl Trait 返回值静态+膨胀零
Box<dyn Trait>动态最小分配 + vtable

语法对比

// Static dispatch - type known at compile time
fn process(x: impl Display) { }      // argument position
fn process<T: Display>(x: T) { }     // explicit generic
fn get() -> impl Display { }         // return position

// Dynamic dispatch - type determined at runtime
fn process(x: &dyn Display) { }      // reference
fn process(x: Box<dyn Display>) { }  // owned

错误代码参考

错误原因快速修复
E0277类型未实现 trait添加 impl 或更改约束
E0308类型不匹配检查泛型参数
E0599未找到方法使用 use 导入 trait
E0038Trait 不满足对象安全使用泛型或重新设计

决策指南

场景选择原因
性能关键泛型零运行时开销
异构集合dyn Trait运行时类型不同
插件架构dyn Trait编译时类型未知
缩短编译时间dyn Trait减少单态化
类型集合小且已知enum无间接寻址

对象安全

trait 满足以下条件时,即为对象安全:

  • 不带 Self: Sized 约束
  • 不返回 Self
  • 不包含泛型方法
  • 对非对象安全方法使用 where Self: Sized

反模式

反模式不妥之处更好的做法
所有东西都过度泛型化编译时间、复杂性尽可能使用具体类型
对已知类型使用 dyn不必要的间接寻址泛型
复杂的 trait 层级结构难以理解简化设计
忽略对象安全限制灵活性有需要时规划使用 dyn

相关技能

情况查看
类型驱动设计m05-type-driven
领域抽象m09-domain
性能问题m10-performance
Send/Sync 约束m07-concurrency

评论

支持 Markdown