m04-zero-cost

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zero-Cost Abstraction

零成本抽象

Layer 1: Language Mechanics
第一层:语言机制

Core Question

核心问题

Do we need compile-time or runtime polymorphism?
Before choosing between generics and trait objects:
  • Is the type known at compile time?
  • Is a heterogeneous collection needed?
  • What's the performance priority?

我们需要编译时多态还是运行时多态?
在选择泛型和Trait对象之前,请考虑:
  • 类型是否在编译时已知?
  • 是否需要异构集合?
  • 性能优先级是什么?

Error → Design Question

错误 → 设计问题

ErrorDon't Just SayAsk Instead
E0277"Add trait bound"Is this abstraction at the right level?
E0308"Fix the type"Should types be unified or distinct?
E0599"Import the trait"Is the trait the right abstraction?
E0038"Make object-safe"Do we really need dynamic dispatch?

错误码不要只说而是要问
E0277"添加Trait约束"这个抽象的层级是否合适?
E0308"修复类型"类型应该统一还是保持不同?
E0599"导入Trait"这个Trait是合适的抽象吗?
E0038"使对象安全"我们真的需要动态分发吗?

Thinking Prompt

思考提示

Before adding trait bounds:
  1. What abstraction is needed?
    • Same behavior, different types → trait
    • Different behavior, same type → enum
    • No abstraction needed → concrete type
  2. When is type known?
    • Compile time → generics (static dispatch)
    • Runtime → trait objects (dynamic dispatch)
  3. What's the trade-off priority?
    • Performance → generics
    • Compile time → trait objects
    • Flexibility → depends

在添加Trait约束之前:
  1. 需要什么样的抽象?
    • 行为相同、类型不同 → Trait
    • 行为不同、类型相同 → 枚举(enum)
    • 不需要抽象 → 具体类型
  2. 类型何时确定?
    • 编译时 → 泛型(静态分发)
    • 运行时 → Trait对象(动态分发)
  3. 权衡优先级是什么?
    • 性能 → 泛型
    • 编译时间 → Trait对象
    • 灵活性 → 视情况而定

Trace Up ↑

向上追溯 ↑

When type system fights back:
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?)
Persistent ErrorTrace ToQuestion
Complex trait boundsm09-domainIs the abstraction right?
Object safety issuesm05-type-drivenCan typestate help?
Type explosionm10-performanceAccept dyn overhead?

当类型系统发出警告时:
E0277(Trait约束不满足)
    ↑ 提问:抽象层级是否正确?
    ↑ 检查:m09-domain(正在抽象的是什么行为?)
    ↑ 检查:m05-type-driven(是否应该使用newtype?)
持续出现的错误追溯至问题
复杂Trait约束m09-domain这个抽象是否合适?
对象安全问题m05-type-driven类型状态(typestate)能否提供帮助?
类型爆炸m10-performance是否接受dyn的开销?

Trace Down ↓

向下推导 ↓

From design to implementation:
"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>

从设计到实现:
"需要对具有相同行为的类型进行抽象"
    ↓ 编译时已知类型 → impl Trait 或 泛型
    ↓ 运行时确定类型 → dyn Trait

"需要不同类型的集合"
    ↓ 封闭类型集合 → enum
    ↓ 开放类型集合 → Vec<Box<dyn Trait>>

"需要返回不同类型"
    ↓ 相同类型 → impl Trait
    ↓ 不同类型 → Box<dyn Trait>

Quick Reference

快速参考

PatternDispatchCode SizeRuntime Cost
fn foo<T: Trait>()
Static+bloatZero
fn foo(x: &dyn Trait)
DynamicMinimalvtable lookup
impl Trait
return
Static+bloatZero
Box<dyn Trait>
DynamicMinimalAllocation + vtable
模式分发方式代码体积运行时开销
fn foo<T: Trait>()
静态增大零开销
fn foo(x: &dyn Trait)
动态最小虚表查找
impl Trait
返回值
静态增大零开销
Box<dyn Trait>
动态最小内存分配 + 虚表查找

Syntax Comparison

语法对比

rust
// 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
rust
// 静态分发 - 编译时已知类型
fn process(x: impl Display) { }      // 参数位置
fn process<T: Display>(x: T) { }     // 显式泛型
fn get() -> impl Display { }         // 返回值位置

// 动态分发 - 运行时确定类型
fn process(x: &dyn Display) { }      // 引用
fn process(x: Box<dyn Display>) { }  // 所有权

Error Code Reference

错误码参考

ErrorCauseQuick Fix
E0277Type doesn't impl traitAdd impl or change bound
E0308Type mismatchCheck generic params
E0599No method foundImport trait with
use
E0038Trait not object-safeUse generics or redesign

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

Decision Guide

决策指南

ScenarioChooseWhy
Performance criticalGenericsZero runtime cost
Heterogeneous collection
dyn Trait
Different types at runtime
Plugin architecture
dyn Trait
Unknown types at compile
Reduce compile time
dyn Trait
Less monomorphization
Small, known type set
enum
No indirection

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

Object Safety

对象安全

A trait is object-safe if it:
  • Doesn't have
    Self: Sized
    bound
  • Doesn't return
    Self
  • Doesn't have generic methods
  • Uses
    where Self: Sized
    for non-object-safe methods

Trait满足以下条件时支持对象安全:
  • 没有
    Self: Sized
    约束
  • 不返回
    Self
  • 没有泛型方法
  • 对非对象安全的方法使用
    where Self: Sized
    约束

Anti-Patterns

反模式

Anti-PatternWhy BadBetter
Over-generic everythingCompile time, complexityConcrete types when possible
dyn
for known types
Unnecessary indirectionGenerics
Complex trait hierarchiesHard to understandSimpler design
Ignore object safetyLimits flexibilityPlan for dyn if needed

反模式问题所在更好的方案
一切都过度泛型化编译时间长、复杂度高尽可能使用具体类型
已知类型使用
dyn
不必要的间接开销泛型
复杂Trait层级难以理解更简洁的设计
忽略对象安全限制灵活性若需要则提前规划dyn的使用

Related Skills

相关技能

WhenSee
Type-driven designm05-type-driven
Domain abstractionm09-domain
Performance concernsm10-performance
Send/Sync boundsm07-concurrency
场景参考
类型驱动设计m05-type-driven
领域抽象m09-domain
性能相关问题m10-performance
Send/Sync约束m07-concurrency