#error #traits #try #unstable #tracing #call-stack #time

nightly traced_result

使用 Try 特性实现的概念验证错误跟踪

1 个不稳定版本

0.1.0 2024年7月25日

#627Rust 模式

Download history 96/week @ 2024-07-20 31/week @ 2024-07-27

每月下载 127 次

MIT 许可证

13KB
192

traced_result

一个概念验证,用于自动回溯使用 ? 操作符传播的错误

注意:此 crate 依赖于不稳定语言特性 try_trait_v2。这意味着它只能与 nightly 工具链一起使用,可能随时会中断,因此不建议在生产代码中使用,直到该特性稳定。

用法

traced_result 与像 trace_error 这样的 crate 不同,因为它不使用宏来跟踪调用堆栈,而是使用(目前不稳定)的 Try 特性尽可能与常规 Result 保持一致。此 crate 的核心类型是 TracedResult<T, E>,设计用来像 std::result::Result<T, E> 一样工作,以及 TracedError<E>,它只是 E 的包装和一个 Vec<&'static Location<'static>>。要开始,只需将 Result 替换为 TracedResult

// From
fn foo() -> Result<Bar, Baz> {
    // ...
    return Err(Baz(/*...*/));
}

// To
fn foo() -> TracedResult<Bar, Baz> {
    // ...
    return TracedResult::Err(TracedError::new(Baz(/*...*/)))
}

TracedResultTracedError 还提供了方便的 From 实现,允许你编写如下内容

    return TracedResult::Err(Baz(/*...*/).into()) 

或者甚至

return Err(Baz(/*...*/)).into() 

现在,每当使用 ? 操作符传播 TracedResult 时,TracedResultTry 实现将存储操作符使用位置到错误的调用堆栈中(如果有的话)

fn foo() -> TracedResult<Bar, Baz> {
    Err(Baz(/*...*/)).into()
}

fn do_something() -> TracedResult<(), Baz> {
    let value = foo()?; 
    Ok(())
}

fn main() {
    if let TracedResult::Err(error) = do_something() {
        println!("{}", error) 
        // Baz at (40:21) in file example.rs
        // at (2:26) in file example.rs
    }
}

Result 方法

TracedResult<T, E> 目前有以下方法

  • unwrap() 及所有相关方法,包括 unchecked 方法
  • is_ok()is_err()
  • map() 及所有相关方法
  • 转换为 std::result::Result<T, TracedError<E>> 使用 into_result()From trait 以保持兼容性,任何剩余的方法——注意,后续使用 ? 操作符将不再被跟踪。要完全丢弃调用栈,也可以使用 TracedResult::discard_call_stack() 来获取一个不带 TracedError 包装器围绕 EResult<T, E>

注意:#[track_caller] 属性

内部,TracedResult 使用 #[track_caller] 属性来获取使用 ? 操作符的位置。这意味着如果结果是从一个本身带有 #[track_caller] 注解的函数中传播的,则添加到调用栈的 Location 将是函数调用者的位置,而不是 Try 操作符本身的位置。

无运行时依赖