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

如何获取proc宏内部错误发生位置的追踪信息?

在Rust Proc宏中显示实现内错误位置的方法

方法一:使用proc_macro_error crate

这是最简便的实现方式,该 crate 会自动捕获 proc 宏中的 panic,并将 panic 的完整追踪信息(包括宏实现内的文件路径、行号)附加到编译错误中。

  • 在 proc 宏 crate 的Cargo.toml中添加依赖:
    [dependencies]
    proc-macro-error = "1.0"
    
  • 在 proc 宏的入口函数上添加#[proc_macro_error]属性:
    use proc_macro_error::proc_macro_error;
    
    #[proc_macro_error]
    #[proc_macro]
    pub fn my_macro(input: TokenStream) -> TokenStream {
        // 宏实现代码,即使此处panic,也会显示实现内的追踪信息
        panic!("宏内部执行出错");
    }
    
  • 编译客户端 crate 时,错误信息会包含宏实现内的 panic 位置,示例如下:
    error: proc macro panicked
      --> foo/src/main.rs:17:1
       |
    17 | #[my_macro]
       | ^^^^^^^^^^^
       |
       = help: panicked at '宏内部执行出错', proc_macro_crate/src/lib.rs:10:5
    

方法二:手动构建带位置的诊断信息(无额外依赖)

如果不想引入第三方 crate,可以利用 Rust 标准库的proc_macro::Diagnostic(Rust 1.59+ 稳定版支持)结合file!和line!宏,手动添加实现内的位置信息:

use proc_macro::{Diagnostic, Level, TokenStream};

#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
    // 模拟错误触发场景
    let error_occurred = true;
    if error_occurred {
        Diagnostic::new(Level::Error, "宏内部执行出错")
            .note(format!("错误起源位置:{}:{}", file!(), line!()))
            .emit();
        return TokenStream::new();
    }

    // 正常宏逻辑处理
    input
}

编译客户端 crate 时,错误信息会显示:

error: 宏内部执行出错
  --> foo/src/main.rs:17:1
   |
17 | #[my_macro]
   | ^^^^^^^^^^^
   |
   = note: 错误起源位置:proc_macro_crate/src/lib.rs:12:9

方法三:自定义 panic hook

在 proc 宏启动时设置自定义 panic hook,将 panic 的追踪信息注入到编译错误中:

use std::panic;
use proc_macro::TokenStream;

#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
    // 保存原panic hook,后续可恢复
    let original_hook = panic::take_hook();
    panic::set_hook(Box::new(move |panic_info| {
        original_hook(panic_info);
        // 将panic信息转换为编译诊断
        if let Some(location) = panic_info.location() {
            let msg = format!("宏内部panic:{},位置:{}:{}", panic_info.to_string(), location.file(), location.line());
            proc_macro::Diagnostic::new(proc_macro::Level::Error, msg).emit();
        }
    }));

    // 宏实现代码
    panic!("测试panic场景");

    // 恢复原hook(实际panic后不会执行到此处,可结合Drop guard优化)
    panic::set_hook(original_hook);
    TokenStream::new()
}

这种方式能捕获所有未处理的 panic,并自动将实现内的位置信息添加到编译诊断中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:06:29