Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
test rustc_lint rustc_const_eval


TOOL_DEPS_compiletest := test getopts log
TOOL_DEPS_compiletest := test getopts log serialize
TOOL_DEPS_rustdoc := rustdoc
TOOL_DEPS_rustc := rustc_driver
TOOL_DEPS_rustbook := std rustdoc
Expand Down
50 changes: 50 additions & 0 deletions src/libsyntax/codemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,56 @@ impl CodeMap {
pub fn count_lines(&self) -> usize {
self.files.borrow().iter().fold(0, |a, f| a + f.count_lines())
}

pub fn macro_backtrace(&self, span: Span) -> Vec<MacroBacktrace> {
let mut last_span = DUMMY_SP;
let mut span = span;
let mut result = vec![];
loop {
let span_name_span = self.with_expn_info(span.expn_id, |expn_info| {
expn_info.map(|ei| {
let (pre, post) = match ei.callee.format {
MacroAttribute(..) => ("#[", "]"),
MacroBang(..) => ("", "!"),
};
let macro_decl_name = format!("{}{}{}",
pre,
ei.callee.name(),
post);
let def_site_span = ei.callee.span;
(ei.call_site, macro_decl_name, def_site_span)
})
});

match span_name_span {
None => break,
Some((call_site, macro_decl_name, def_site_span)) => {
// Don't print recursive invocations
if !call_site.source_equal(&last_span) {
result.push(MacroBacktrace {
call_site: call_site,
macro_decl_name: macro_decl_name,
def_site_span: def_site_span,
});
}
last_span = span;
span = call_site;
}
}
}
result
}
}

pub struct MacroBacktrace {
/// span where macro was applied to generate this code
pub call_site: Span,

/// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
pub macro_decl_name: String,

/// span where macro was defined (if known)
pub def_site_span: Option<Span>,
}

// _____________________________________________________________________________
Expand Down
47 changes: 9 additions & 38 deletions src/libsyntax/errors/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,46 +577,17 @@ impl EmitterWriter {
fn print_macro_backtrace(&mut self,
sp: Span)
-> io::Result<()> {
let mut last_span = codemap::DUMMY_SP;
let mut span = sp;

loop {
let span_name_span = self.cm.with_expn_info(span.expn_id, |expn_info| {
expn_info.map(|ei| {
let (pre, post) = match ei.callee.format {
codemap::MacroAttribute(..) => ("#[", "]"),
codemap::MacroBang(..) => ("", "!"),
};
let macro_decl_name = format!("in this expansion of {}{}{}",
pre,
ei.callee.name(),
post);
let def_site_span = ei.callee.span;
(ei.call_site, macro_decl_name, def_site_span)
})
});
let (macro_decl_name, def_site_span) = match span_name_span {
None => break,
Some((sp, macro_decl_name, def_site_span)) => {
span = sp;
(macro_decl_name, def_site_span)
}
};

// Don't print recursive invocations
if !span.source_equal(&last_span) {
let mut diag_string = macro_decl_name;
if let Some(def_site_span) = def_site_span {
diag_string.push_str(&format!(" (defined in {})",
self.cm.span_to_filename(def_site_span)));
}

let snippet = self.cm.span_to_string(span);
print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?;
for trace in self.cm.macro_backtrace(sp) {
let mut diag_string =
format!("in this expansion of {}", trace.macro_decl_name);
if let Some(def_site_span) = trace.def_site_span {
diag_string.push_str(
&format!(" (defined in {})",
self.cm.span_to_filename(def_site_span)));
}
last_span = span;
let snippet = self.cm.span_to_string(sp);
print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?;
}

Ok(())
}
}
Expand Down
Loading