Skip to content

Commit b7ec248

Browse files
kevinabrson
authored andcommitted
Fix macro backtraces.
In addition add information about the macro doing the expansion, and move the printing of the expansion backtrace from codemap::span_to_str to the diagnostic code. The backtrace is now more verbose and includes information on the macro doing the expansion, in addition to the expansion site.
1 parent 1d855eb commit b7ec248

File tree

7 files changed

+72
-59
lines changed

7 files changed

+72
-59
lines changed

src/comp/driver/diagnostic.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ fn emit(cmsp: option<(codemap::codemap, span)>,
179179
let lines = codemap::span_to_lines(sp, cm);
180180
print_diagnostic(ss, lvl, msg);
181181
highlight_lines(cm, sp, lines);
182+
print_macro_backtrace(cm, sp);
182183
}
183184
none {
184185
print_diagnostic("", lvl, msg);
@@ -241,3 +242,15 @@ fn highlight_lines(cm: codemap::codemap, sp: span,
241242
io::stderr().write_str(s + "\n");
242243
}
243244
}
245+
246+
fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
247+
option::may (sp.expn_info) {|ei|
248+
let ss = option::maybe("", ei.callie.span,
249+
bind codemap::span_to_str(_, cm));
250+
print_diagnostic(ss, note,
251+
#fmt("in expansion of #%s", ei.callie.name));
252+
let ss = codemap::span_to_str(ei.call_site, cm);
253+
print_diagnostic(ss, note, "expansion site");
254+
print_macro_backtrace(cm, ei.call_site);
255+
}
256+
}

src/comp/front/core_inject.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn inject_libcore_ref(sess: session,
2424
fn spanned<T: copy>(x: T) -> @ast::spanned<T> {
2525
ret @{node: x,
2626
span: {lo: 0u, hi: 0u,
27-
expanded_from: codemap::os_none}};
27+
expn_info: option::none}};
2828
}
2929

3030
let n1 = sess.next_node_id();

src/comp/syntax/ast_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn respan<T: copy>(sp: span, t: T) -> spanned<T> {
77

88
/* assuming that we're not in macro expansion */
99
fn mk_sp(lo: uint, hi: uint) -> span {
10-
ret {lo: lo, hi: hi, expanded_from: codemap::os_none};
10+
ret {lo: lo, hi: hi, expn_info: none};
1111
}
1212

1313
// make this a const, once the compiler supports it

src/comp/syntax/codemap.rs

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -92,38 +92,18 @@ fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
9292
ret lookup_pos(map, pos, lookup);
9393
}
9494

95-
enum opt_span {
96-
97-
//hack (as opposed to option), to make `span` compile
98-
os_none,
99-
os_some(@span),
95+
enum expn_info_ {
96+
expanded_from({call_site: span,
97+
callie: {name: str, span: option<span>}})
10098
}
101-
type span = {lo: uint, hi: uint, expanded_from: opt_span};
99+
type expn_info = option<@expn_info_>;
100+
type span = {lo: uint, hi: uint, expn_info: expn_info};
102101

103102
fn span_to_str(sp: span, cm: codemap) -> str {
104-
let cur = sp;
105-
let res = "";
106-
// FIXME: Should probably be doing pointer comparison on filemap
107-
let prev_file = none;
108-
while true {
109-
let lo = lookup_char_pos(cm, cur.lo);
110-
let hi = lookup_char_pos(cm, cur.hi);
111-
res +=
112-
#fmt["%s:%u:%u: %u:%u",
113-
if some(lo.file.name) == prev_file {
114-
"-"
115-
} else { lo.file.name }, lo.line, lo.col, hi.line, hi.col];
116-
alt cur.expanded_from {
117-
os_none { break; }
118-
os_some(new_sp) {
119-
cur = *new_sp;
120-
prev_file = some(lo.file.name);
121-
res += "<<";
122-
}
123-
}
124-
}
125-
126-
ret res;
103+
let lo = lookup_char_pos(cm, sp.lo);
104+
let hi = lookup_char_pos(cm, sp.hi);
105+
ret #fmt("%s:%u:%u: %u:%u", lo.file.name,
106+
lo.line, lo.col, hi.line, hi.col)
127107
}
128108

129109
type file_lines = {file: filemap, lines: [uint]};

src/comp/syntax/ext/base.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import core::{vec, option};
22
import std::map::hashmap;
33
import driver::session::session;
4-
import codemap::span;
4+
import codemap::{span, expn_info, expanded_from};
55
import std::map::new_str_hash;
66
import codemap;
77

8-
type syntax_expander =
8+
type syntax_expander_ =
99
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> @ast::expr;
10+
type syntax_expander = {
11+
expander: syntax_expander_,
12+
span: option<span>};
1013
type macro_def = {ident: str, ext: syntax_extension};
1114
type macro_definer =
1215
fn@(ext_ctxt, span, ast::mac_arg, ast::mac_body) -> macro_def;
@@ -19,27 +22,29 @@ enum syntax_extension {
1922
// A temporary hard-coded map of methods for expanding syntax extension
2023
// AST nodes into full ASTs
2124
fn syntax_expander_table() -> hashmap<str, syntax_extension> {
25+
fn builtin(f: syntax_expander_) -> syntax_extension
26+
{normal({expander: f, span: none})}
2227
let syntax_expanders = new_str_hash::<syntax_extension>();
23-
syntax_expanders.insert("fmt", normal(ext::fmt::expand_syntax_ext));
24-
syntax_expanders.insert("env", normal(ext::env::expand_syntax_ext));
28+
syntax_expanders.insert("fmt", builtin(ext::fmt::expand_syntax_ext));
29+
syntax_expanders.insert("env", builtin(ext::env::expand_syntax_ext));
2530
syntax_expanders.insert("macro",
2631
macro_defining(ext::simplext::add_new_extension));
2732
syntax_expanders.insert("concat_idents",
28-
normal(ext::concat_idents::expand_syntax_ext));
33+
builtin(ext::concat_idents::expand_syntax_ext));
2934
syntax_expanders.insert("ident_to_str",
30-
normal(ext::ident_to_str::expand_syntax_ext));
35+
builtin(ext::ident_to_str::expand_syntax_ext));
3136
syntax_expanders.insert("log_syntax",
32-
normal(ext::log_syntax::expand_syntax_ext));
37+
builtin(ext::log_syntax::expand_syntax_ext));
3338
syntax_expanders.insert("ast",
34-
normal(ext::qquote::expand_ast));
39+
builtin(ext::qquote::expand_ast));
3540
ret syntax_expanders;
3641
}
3742

3843
iface ext_ctxt {
3944
fn session() -> session;
4045
fn print_backtrace();
41-
fn backtrace() -> codemap::opt_span;
42-
fn bt_push(sp: span);
46+
fn backtrace() -> expn_info;
47+
fn bt_push(ei: codemap::expn_info_);
4348
fn bt_pop();
4449
fn span_fatal(sp: span, msg: str) -> !;
4550
fn span_err(sp: span, msg: str);
@@ -51,20 +56,26 @@ iface ext_ctxt {
5156

5257
fn mk_ctxt(sess: session) -> ext_ctxt {
5358
type ctxt_repr = {sess: session,
54-
mutable backtrace: codemap::opt_span};
59+
mutable backtrace: expn_info};
5560
impl of ext_ctxt for ctxt_repr {
5661
fn session() -> session { self.sess }
5762
fn print_backtrace() { }
58-
fn backtrace() -> codemap::opt_span { self.backtrace }
59-
fn bt_push(sp: span) {
60-
self.backtrace = codemap::os_some(
61-
@{lo: sp.lo, hi: sp.hi, expanded_from: self.backtrace});
63+
fn backtrace() -> expn_info { self.backtrace }
64+
fn bt_push(ei: codemap::expn_info_) {
65+
alt ei {
66+
expanded_from({call_site: cs, callie: callie}) {
67+
self.backtrace =
68+
some(@expanded_from({
69+
call_site: {lo: cs.lo, hi: cs.hi,
70+
expn_info: self.backtrace},
71+
callie: callie}));
72+
}
73+
}
6274
}
6375
fn bt_pop() {
6476
alt self.backtrace {
65-
codemap::os_some(@{expanded_from: pre, _}) {
66-
let tmp = pre;
67-
self.backtrace = tmp;
77+
some(@expanded_from({call_site: {expn_info: prev, _}, _})) {
78+
self.backtrace = prev
6879
}
6980
_ { self.bug("tried to pop without a push"); }
7081
}
@@ -88,7 +99,8 @@ fn mk_ctxt(sess: session) -> ext_ctxt {
8899
fn bug(msg: str) -> ! { self.print_backtrace(); self.sess.bug(msg); }
89100
fn next_id() -> ast::node_id { ret self.sess.next_node_id(); }
90101
}
91-
{sess: sess, mutable backtrace: codemap::os_none} as ext_ctxt
102+
let imp : ctxt_repr = {sess: sess, mutable backtrace: none};
103+
ret imp as ext_ctxt
92104
}
93105

94106
fn expr_to_str(cx: ext_ctxt, expr: @ast::expr, error: str) -> str {

src/comp/syntax/ext/expand.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import syntax::ext::base::*;
1111
import syntax::ext::qquote::{expand_qquote,qq_helper};
1212
import syntax::parse::parser::parse_expr_from_source_str;
1313

14-
import codemap::span;
14+
import codemap::{span, expanded_from};
1515

1616
fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
1717
e: expr_, s: span, fld: ast_fold,
@@ -29,10 +29,12 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
2929
cx.span_fatal(pth.span,
3030
#fmt["macro undefined: '%s'", extname])
3131
}
32-
some(normal(ext)) {
33-
let expanded = ext(cx, pth.span, args, body);
32+
some(normal({expander: exp, span: exp_sp})) {
33+
let expanded = exp(cx, pth.span, args, body);
3434

35-
cx.bt_push(mac.span);
35+
let info = {call_site: s,
36+
callie: {name: extname, span: exp_sp}};
37+
cx.bt_push(expanded_from(info));
3638
//keep going, outside-in
3739
let fully_expanded = fld.fold_expr(expanded).node;
3840
cx.bt_pop();
@@ -53,6 +55,11 @@ fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt,
5355
};
5456
}
5557

58+
fn new_span(cx: ext_ctxt, sp: span) -> span {
59+
/* this discards information in the case of macro-defining macros */
60+
ret {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
61+
}
62+
5663
// FIXME: this is a terrible kludge to inject some macros into the default
5764
// compilation environment. When the macro-definition system is substantially
5865
// more mature, these should move from here, into a compiled part of libcore
@@ -73,7 +80,8 @@ fn expand_crate(sess: session::session, c: @crate) -> @crate {
7380
let afp = default_ast_fold();
7481
let cx: ext_ctxt = mk_ctxt(sess);
7582
let f_pre =
76-
{fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr)
83+
{fold_expr: bind expand_expr(exts, cx, _, _, _, afp.fold_expr),
84+
new_span: bind new_span(cx, _)
7785
with *afp};
7886
let f = make_fold(f_pre);
7987
let cm = parse_expr_from_source_str("<core-macros>",

src/comp/syntax/ext/simplext.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ fn transcribe(cx: ext_ctxt, b: bindings, body: @expr) -> @expr {
190190
fn new_id(_old: node_id, cx: ext_ctxt) -> node_id { ret cx.next_id(); }
191191
fn new_span(cx: ext_ctxt, sp: span) -> span {
192192
/* this discards information in the case of macro-defining macros */
193-
ret {lo: sp.lo, hi: sp.hi, expanded_from: cx.backtrace()};
193+
ret {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
194194
}
195195
let afp = default_ast_fold();
196196
let f_pre =
@@ -202,8 +202,8 @@ fn transcribe(cx: ext_ctxt, b: bindings, body: @expr) -> @expr {
202202
fold_block:
203203
bind transcribe_block(cx, b, idx_path, _, _, _, afp.fold_block),
204204
map_exprs: bind transcribe_exprs(cx, b, idx_path, _, _),
205-
new_id: bind new_id(_, cx),
206-
new_span: bind new_span(cx, _) with *afp};
205+
new_id: bind new_id(_, cx)
206+
with *afp};
207207
let f = make_fold(f_pre);
208208
let result = f.fold_expr(body);
209209
ret result;
@@ -753,7 +753,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
753753
"at least one clause")
754754
}
755755
},
756-
ext: normal(ext)};
756+
ext: normal({expander: ext, span: some(arg.span)})};
757757

758758
fn generic_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
759759
_body: ast::mac_body, clauses: [@clause]) -> @expr {

0 commit comments

Comments
 (0)