我希望我的程序宏用方法替换一些BinaryOps。如何设置跨度,以便在发生错误时我的用户不会完全混淆?
答案 0 :(得分:1)
在研究了rustc
的来源之后,我得出的结论是,在“扩展”模型之后产生了最好的结果。因此,我们保留原始Span
,但保留expn_id
,我们可以通过调用ExtCtxt::backtrace()
来获取。{/ p>
在问题中概述的两种情况下设置此类似乎是个好主意。可以看到运算符扩展为(函数调用)路径,并将原始二进制操作表达式扩展为函数调用。在代码中:
match expr.unwrap() {
..
Expr { node: ExprKind::Binary( Spanned { node: Add, span: op }, l, r), span, .. } => {
let bt = self.cx.backtrace(); // get the expansion ID
let path = self.cx.path(Span { expn_id: bt, ..op }, vec![crate_name, trait_name, fn_name]);
let epath = self.cx.expr_path(path); // path expression
let args_expanded = self.fold_exprs(args);
self.cx.expr_call(Span { expn_id: bt, ..span }, epath, args_expanded)
// ^ outer expression
}
..
}