处理Rust错误Skill handling-rust-errors

这个技能描述了在Rust编程中使用error-stack crate进行错误处理的最佳实践和模式,包括定义自定义错误、使用Report类型、通过change_context传播错误、用attach添加上下文,以及实现Error trait。适用于需要一致和可调试错误处理的Rust项目,如后端开发、系统编程和嵌入式软件。关键词:Rust,错误处理,error-stack,Report类型,上下文传播,自定义错误,Result类型,HASH项目。

后端开发 0 次安装 0 次浏览 更新于 3/11/2026

name: handling-rust-errors description: 使用error-stack crate的HASH错误处理模式。适用于处理Result类型、Report类型、定义自定义错误、使用change_context传播错误、使用attach添加上下文、实现Error trait或在Rust代码中记录错误条件。 license: AGPL-3.0 metadata: triggers: type: domain enforcement: suggest priority: high keywords: - 错误 - Result - Report - error-stack - change_context - attach - ResultExt intent-patterns: - “\b(处理|创建|定义|传播|转换)\b.?\b错误\b" - "\bReport<.>\b”

Rust错误处理模式

使用error-stack crate的HASH特定错误处理模式,以在整个Rust代码库中实现一致和可调试的错误处理。

核心原则

HASH独家使用error-stack进行错误处理:

做:

  • 对所有错误类型使用Report<MyError>
  • 使用具体错误类型:Report<MyError>
  • core::error::导入Error(而非std::error::
  • 导入ResultExt as _以使用trait方法

不做:

  • 使用anyhoweyre crate
  • 使用Box<dyn Error>(测试或原型设计除外)
  • 使用Report<Box<dyn Error>>
  • 使用thiserror(使用derive_more替代)

HashQL编译器例外

HashQL编译器代码使用不同的错误处理方法。

位于libs/@local/hashql/*的代码使用hashql-diagnostics crate而非error-stack。这是因为编译器错误需要丰富的格式化功能:

  • 指向精确代码位置的源范围
  • 同一诊断中的多个标记区域
  • 带有替换文本的修复建议
  • 严重级别(错误、警告、提示)

使用方法:

位置 错误处理
libs/@local/hashql/*(编译器代码) 使用hashql-diagnostics → 参见writing-hashql-diagnostics技能
其他所有地方 使用本技能中的error-stack模式

传统的error-stack模式仍适用于HashQL基础设施代码(CLI、文件I/O、配置),这些不涉及编译器诊断。

快速入门指南

选择与当前任务匹配的参考:

定义错误

当: 创建新错误类型或错误枚举时使用

  • 使用derive_more定义错误类型
  • 错误枚举模式和变体
  • 实现Error trait
  • 错误类型层次结构

传播错误

当: 处理Result类型、使用?操作符时使用

  • 使用.change_context().change_context_with()转换错误
  • 使用.attach().attach_with()添加上下文
  • 错误转换模式

记录错误

当: 为可能失败的函数编写文档注释时使用

  • # 错误部分的格式
  • 链接错误变体
  • 记录运行时错误
  • 测试错误条件

常见快速模式

创建错误

use error_stack::Report;

return Err(Report::new(MyError::NotFound))
    .attach(format!("ID: {}", id));

添加上下文传播错误

use error_stack::ResultExt as _;

some_result
    .change_context(MyError::OperationFailed)
    .attach("额外上下文")?;

惰性上下文(用于昂贵操作)

use error_stack::ResultExt as _;

expensive_operation()
    .change_context(MyError::OperationFailed)
    .attach_with(|| format!("调试信息: {:?}", expensive_computation()))?;

参考