You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Box<dyn std::error::Error>通过?获取错误发生行号?

适配Box的行号错误实现

要让Box<dyn std::error::Error>带上错误发生的行号,我们可以通过自定义错误结构体+宏的方式实现,满足你期望的代码逻辑(稍作调整以适配位置捕获):

1. 定义带位置的错误结构体

首先定义LocatedError,用于包裹原始错误和调用位置:

use std::error::Error;
use std::fmt;
use std::panic::Location;

#[derive(Debug)]
struct LocatedError {
    inner: Box<dyn Error>,
    location: &'static Location<'static>,
}

2. 实现Display和Error trait

让错误能正确打印,同时保留原始错误的源信息:

impl fmt::Display for LocatedError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "错误: {},发生在: {}", self.inner, self.location)
    }
}

impl Error for LocatedError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.inner.source()
    }
}

3. 通用错误转换与位置捕获

实现一个通用转换函数,把任意错误类型包装成LocatedError并捕获当前位置:

trait IntoLocatedError {
    fn into_located(self) -> LocatedError;
}

impl<E: Error + 'static> IntoLocatedError for E {
    fn into_located(self) -> LocatedError {
        LocatedError {
            inner: Box::new(self),
            location: Location::caller(),
        }
    }
}

// 为Box<dyn Error>实现转换,支持嵌套错误
impl IntoLocatedError for Box<dyn Error> {
    fn into_located(self) -> LocatedError {
        LocatedError {
            inner: self,
            location: Location::caller(),
        }
    }
}

4. 自定义宏替代?运算符

由于标准?无法直接捕获调用位置,我们用一个宏实现类似?的功能,自动添加位置信息:

macro_rules! try_loc {
    ($expr:expr) => {
        match $expr {
            Ok(val) => val,
            Err(e) => return Err(e.into_located()),
        }
    };
}

5. 使用示例

现在可以按照需求编写代码,只需把?替换为try_loc!:

fn main() -> Result<(), LocatedError> {
    try_loc!(std::fs::File::open("blurb.txt"));
    Ok(())
}

运行后,如果文件不存在,会输出类似:

错误: No such file or directory (os error 2),发生在: src/main.rs:25:5

补充说明

如果一定要用标准?运算符,需要自定义Result类型并实现From trait,但这样无法捕获正确的调用位置(Location::caller()会指向From实现的位置而非用户代码的?位置),所以宏是更可靠的方案。

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:16:06