After some study of the source of rustc I came to the conclusion that after the βextension modelβ the best results. Therefore, we keep the original Span , but for expn_id , which we can get by calling ExtCtxt::backtrace() .
It seems like a good idea to establish this in both cases outlined in the question. An operator can be considered as extended to a path (function call) and the original expression of a binary operation extended to a function call. In code:
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 } .. }
source share