Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show macro backtrace with -Z flag #45545

Merged
merged 7 commits into from
Nov 21, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 5 additions & 3 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
"treat all errors that occur as bugs"),
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces even for non-local macros"),
continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
"attempt to recover from parse errors (experimental)"),
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
Expand Down Expand Up @@ -2100,7 +2102,7 @@ mod tests {
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
assert!(!sess.diagnostic().can_emit_warnings);
assert!(!sess.diagnostic().flags.can_emit_warnings);
}

{
Expand All @@ -2111,7 +2113,7 @@ mod tests {
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
assert!(sess.diagnostic().can_emit_warnings);
assert!(sess.diagnostic().flags.can_emit_warnings);
}

{
Expand All @@ -2121,7 +2123,7 @@ mod tests {
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
assert!(sess.diagnostic().can_emit_warnings);
assert!(sess.diagnostic().flags.can_emit_warnings);
}
}

Expand Down
15 changes: 11 additions & 4 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,10 +727,12 @@ pub fn build_session_with_codemap(sopts: config::Options,
.unwrap_or(false);
let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);

let can_print_warnings = !(warnings_allow || cap_lints_allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);

let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;

let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;

let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
(config::ErrorOutputType::HumanReadable(color_config), None) => {
Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), false))
Expand All @@ -753,9 +755,14 @@ pub fn build_session_with_codemap(sopts: config::Options,
};

let diagnostic_handler =
errors::Handler::with_emitter(can_print_warnings,
treat_err_as_bug,
emitter);
errors::Handler::with_emitter_and_flags(
emitter,
errors::HandlerFlags {
can_emit_warnings,
treat_err_as_bug,
external_macro_backtrace,
.. Default::default()
});

build_session_(sopts,
local_crate_source_file,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use syntax_pos::{MultiSpan, Span};
#[must_use]
#[derive(Clone)]
pub struct DiagnosticBuilder<'a> {
handler: &'a Handler,
pub handler: &'a Handler,
diagnostic: Diagnostic,
}

Expand Down
55 changes: 50 additions & 5 deletions src/librustc_errors/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ impl Emitter for EmitterWriter {
}
}

self.fix_multispans_in_std_macros(&mut primary_span, &mut children);
if !db.handler.flags.external_macro_backtrace {
self.fix_multispans_in_std_macros(&mut primary_span, &mut children);
}
self.emit_messages_default(&db.level,
db.handler.flags.external_macro_backtrace,
&db.styled_message(),
&db.code,
&primary_span,
Expand Down Expand Up @@ -793,8 +796,11 @@ impl EmitterWriter {
if spans_updated {
children.push(SubDiagnostic {
level: Level::Note,
message: vec![("this error originates in a macro outside of the current crate"
.to_string(), Style::NoStyle)],
message: vec![
(["this error originates in a macro outside of the current crate",
"(run with -Z external-macro-backtrace for more info)"].join(" "),
Style::NoStyle),
],
span: MultiSpan::new(),
render_span: None,
});
Expand Down Expand Up @@ -882,6 +888,7 @@ impl EmitterWriter {
msg: &Vec<(String, Style)>,
code: &Option<DiagnosticId>,
level: &Level,
external_macro_backtrace: bool,
max_line_num_len: usize,
is_secondary: bool)
-> io::Result<()> {
Expand Down Expand Up @@ -1079,6 +1086,12 @@ impl EmitterWriter {
}
}

if external_macro_backtrace {
if let Some(ref primary_span) = msp.primary_span().as_ref() {
self.render_macro_backtrace_old_school(primary_span, &mut buffer)?;
}
}

// final step: take our styled buffer, render it, then output it
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;

Expand Down Expand Up @@ -1170,6 +1183,7 @@ impl EmitterWriter {
}
fn emit_messages_default(&mut self,
level: &Level,
external_macro_backtrace: bool,
message: &Vec<(String, Style)>,
code: &Option<DiagnosticId>,
span: &MultiSpan,
Expand All @@ -1178,7 +1192,13 @@ impl EmitterWriter {
let max_line_num = self.get_max_line_num(span, children);
let max_line_num_len = max_line_num.to_string().len();

match self.emit_message_default(span, message, code, level, max_line_num_len, false) {
match self.emit_message_default(span,
message,
code,
level,
external_macro_backtrace,
max_line_num_len,
false) {
Ok(()) => {
if !children.is_empty() {
let mut buffer = StyledBuffer::new();
Expand All @@ -1198,6 +1218,7 @@ impl EmitterWriter {
&child.styled_message(),
&None,
&child.level,
external_macro_backtrace,
max_line_num_len,
true) {
Err(e) => panic!("failed to emit error: {}", e),
Expand Down Expand Up @@ -1226,6 +1247,30 @@ impl EmitterWriter {
}
}
}

fn render_macro_backtrace_old_school(&self,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

old_school isn't very helpful here - what distinguishes it from a normal backtrace? expanded or complete or something might be better

Copy link
Contributor Author

@durka durka Nov 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just used the name from the commit I'm partially reverting. I think it looks a bit "old school" (it doesn't have fancy span notes or anything).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@durka would you be against using the full span machinery for them or would you think it'd be too verbose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more spans the better, probably. I'm afraid I'm not too familiar with the new span hardware. What would it look like?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some changes will need to be made to the macro expansion machinery to avoid bogus spans (<a macros>:1:36: 1:47 note: in this expansion of a! (defined in <a macros>)), but I think it could be made to look something along the lines of:

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
  -->  a/src/lib.rs:6:16
3  |     () => { a!(@) };
   |             ----- in this expansion of `a!` (#2)
4  |     (@) => { a!(@@) };
   |              ------ in this expansion of `a!` (#3)
5  |     (@@) => {
6  |         syntax error;
   |                ^^^^^ expected one of 8 possible tokens here
  ::: src/main.rs
   |
12 |     a!();
   |     ----- in this expansion of `a!` (#1)

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
  --> src/main.rs:7:16
   |
4  |     () => { b!(@) };
   |             ----- in this expansion of `b!` (#2)
5  |     (@) => { b!(@@) };
   |              ------ in this expansion of `b!` (#3)
6  |     (@@) => {
7  |         syntax error;
   |                ^^^^^ expected one of 8 possible tokens here
13 |     b!();
   |     ----- in this expansion of `b!` (#1)

error: aborting due to 2 previous errors

error: Could not compile `b`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that mockup looks really good to me! :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@durka suggestion implemented in #46605. The output is not perfect as it is pointing at the pretty printed expanded macro code instead of the actual code, but it is close enough :)

sp: &Span,
buffer: &mut StyledBuffer) -> io::Result<()> {
if let Some(ref cm) = self.cm {
for trace in sp.macro_backtrace().iter().rev() {
let line_offset = buffer.num_lines();

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 {})",
cm.span_to_filename(def_site_span)));
}
let snippet = cm.span_to_string(trace.call_site);
buffer.append(line_offset, &format!("{} ", snippet), Style::NoStyle);
buffer.append(line_offset, "note", Style::Level(Level::Note));
buffer.append(line_offset, ": ", Style::NoStyle);
buffer.append(line_offset, &diag_string, Style::OldSchoolNoteText);
}
}
Ok(())
}
}

fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
Expand Down Expand Up @@ -1415,7 +1460,7 @@ impl Destination {
}
}
Style::Quotation => {}
Style::HeaderMsg => {
Style::OldSchoolNoteText | Style::HeaderMsg => {
self.start_attr(term::Attr::Bold)?;
if cfg!(windows) {
self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_WHITE))?;
Expand Down
58 changes: 44 additions & 14 deletions src/librustc_errors/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,10 @@ pub use diagnostic_builder::DiagnosticBuilder;
/// (fatal, bug, unimpl) may cause immediate exit,
/// others log errors for later reporting.
pub struct Handler {
pub flags: HandlerFlags,

err_count: Cell<usize>,
emitter: RefCell<Box<Emitter>>,
pub can_emit_warnings: bool,
treat_err_as_bug: bool,
continue_after_error: Cell<bool>,
delayed_span_bug: RefCell<Option<Diagnostic>>,
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
Expand All @@ -247,25 +247,55 @@ pub struct Handler {
emitted_diagnostics: RefCell<FxHashSet<u128>>,
}

#[derive(Default)]
pub struct HandlerFlags {
pub can_emit_warnings: bool,
pub treat_err_as_bug: bool,
pub external_macro_backtrace: bool,
}

impl Handler {
pub fn with_tty_emitter(color_config: ColorConfig,
can_emit_warnings: bool,
treat_err_as_bug: bool,
cm: Option<Rc<CodeMapper>>)
-> Handler {
Handler::with_tty_emitter_and_flags(
color_config,
cm,
HandlerFlags {
can_emit_warnings,
treat_err_as_bug,
.. Default::default()
})
}

pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
cm: Option<Rc<CodeMapper>>,
flags: HandlerFlags)
-> Handler {
let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false));
Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
Handler::with_emitter_and_flags(emitter, flags)
}

pub fn with_emitter(can_emit_warnings: bool,
treat_err_as_bug: bool,
e: Box<Emitter>)
-> Handler {
Handler::with_emitter_and_flags(
e,
HandlerFlags {
can_emit_warnings,
treat_err_as_bug,
.. Default::default()
})
}

pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler {
Handler {
flags,
err_count: Cell::new(0),
emitter: RefCell::new(e),
can_emit_warnings,
treat_err_as_bug,
continue_after_error: Cell::new(true),
delayed_span_bug: RefCell::new(None),
tracked_diagnostics: RefCell::new(None),
Expand Down Expand Up @@ -293,7 +323,7 @@ impl Handler {
-> DiagnosticBuilder<'a> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
result.set_span(sp);
if !self.can_emit_warnings {
if !self.flags.can_emit_warnings {
result.cancel();
}
result
Expand All @@ -306,14 +336,14 @@ impl Handler {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
result.set_span(sp);
result.code(code);
if !self.can_emit_warnings {
if !self.flags.can_emit_warnings {
result.cancel();
}
result
}
pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
if !self.can_emit_warnings {
if !self.flags.can_emit_warnings {
result.cancel();
}
result
Expand Down Expand Up @@ -376,7 +406,7 @@ impl Handler {
}

fn panic_if_treat_err_as_bug(&self) {
if self.treat_err_as_bug {
if self.flags.treat_err_as_bug {
panic!("encountered error with `-Z treat_err_as_bug");
}
}
Expand Down Expand Up @@ -418,7 +448,7 @@ impl Handler {
panic!(ExplicitBug);
}
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
if self.treat_err_as_bug {
if self.flags.treat_err_as_bug {
self.span_bug(sp, msg);
}
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
Expand All @@ -443,15 +473,15 @@ impl Handler {
self.span_bug(sp, &format!("unimplemented {}", msg));
}
pub fn fatal(&self, msg: &str) -> FatalError {
if self.treat_err_as_bug {
if self.flags.treat_err_as_bug {
self.bug(msg);
}
let mut db = DiagnosticBuilder::new(self, Fatal, msg);
db.emit();
FatalError
}
pub fn err(&self, msg: &str) {
if self.treat_err_as_bug {
if self.flags.treat_err_as_bug {
self.bug(msg);
}
let mut db = DiagnosticBuilder::new(self, Error, msg);
Expand Down Expand Up @@ -504,7 +534,7 @@ impl Handler {
panic!(self.fatal(&s));
}
pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
if lvl == Warning && !self.can_emit_warnings {
if lvl == Warning && !self.flags.can_emit_warnings {
return;
}
let mut db = DiagnosticBuilder::new(self, lvl, msg);
Expand All @@ -515,7 +545,7 @@ impl Handler {
}
}
pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl: Level) {
if lvl == Warning && !self.can_emit_warnings {
if lvl == Warning && !self.flags.can_emit_warnings {
return;
}
let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg);
Expand Down
1 change: 1 addition & 0 deletions src/librustc_errors/snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ pub enum Style {
UnderlineSecondary,
LabelPrimary,
LabelSecondary,
OldSchoolNoteText,
NoStyle,
Level(Level),
Highlight,
Expand Down
4 changes: 3 additions & 1 deletion src/librustdoc/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ pub fn run(input: &str,

let codemap = Rc::new(CodeMap::new(sessopts.file_path_mapping()));
let handler =
errors::Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone()));
errors::Handler::with_tty_emitter(ColorConfig::Auto,
true, false,
Some(codemap.clone()));

let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
let mut sess = session::build_session_(
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/parse/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
};

if !self.obsolete_set.contains(&kind) &&
(error || self.sess.span_diagnostic.can_emit_warnings) {
(error || self.sess.span_diagnostic.flags.can_emit_warnings) {
err.note(desc);
self.obsolete_set.insert(kind);
}
Expand Down
Loading