From edb6b025c48205c5084a648c7ef7859adbf5c705 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 14 Mar 2014 10:00:07 +1100 Subject: [PATCH] rustc: make stack traces print for .span_bug/.bug. Previously a call to either of those to diagnostic printers would defer to the `fatal` equivalents, which explicitly silence the stderr printing, including a stack trace from `RUST_LOG=std::rt::backtrace`. This splits the bug printers out to their own diagnostic type so that things work properly. Also, this removes the `Ok(...)` that was being printed around the subtask's stderr output. --- src/librustc/lib.rs | 28 +++++++++++++++++++++------- src/libsyntax/diagnostic.rs | 21 +++++++++++---------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index af0acee07fd..80b36e1dfb1 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -133,6 +133,9 @@ pub mod lib { pub mod llvmdeps; } +static BUG_REPORT_URL: &'static str = + "http://static.rust-lang.org/doc/master/complement-bugreport.html"; + pub fn version(argv0: &str) { let vers = match option_env!("CFG_VERSION") { Some(vers) => vers, @@ -392,20 +395,31 @@ pub fn monitor(f: proc()) { // Task failed without emitting a fatal diagnostic if !value.is::() { let mut emitter = diagnostic::EmitterWriter::stderr(); - emitter.emit( - None, - diagnostic::ice_msg("unexpected failure"), - diagnostic::Error); + + // a .span_bug or .bug call has already printed what + // it wants to print. + if !value.is::() { + emitter.emit( + None, + "unexpected failure", + diagnostic::Bug); + } let xs = [ - ~"the compiler hit an unexpected failure path. \ - this is a bug", + ~"the compiler hit an unexpected failure path. this is a bug.", + "we would appreciate a bug report: " + BUG_REPORT_URL, + ~"run with `RUST_LOG=std::rt::backtrace` for a backtrace", ]; for note in xs.iter() { emitter.emit(None, *note, diagnostic::Note) } - println!("{}", r.read_to_str()); + match r.read_to_str() { + Ok(s) => println!("{}", s), + Err(e) => emitter.emit(None, + format!("failed to read internal stderr: {}", e), + diagnostic::Error), + } } // Fail so the process returns a failure code, but don't pollute the diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 0cf13cfaba5..2da8b786805 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -17,8 +17,6 @@ use std::io; use std::iter::range; use term; -static BUG_REPORT_URL: &'static str = - "http://static.rust-lang.org/doc/master/complement-bugreport.html"; // maximum number of lines we will print for each error; arbitrary. static MAX_LINES: uint = 6u; @@ -34,6 +32,10 @@ pub trait Emitter { /// how a rustc task died (if so desired). pub struct FatalError; +/// Signifies that the compiler died with an explicit call to `.bug` +/// or `.span_bug` rather than a failed assertion, etc. +pub struct ExplicitBug; + // a span-handler is like a handler but also // accepts span information for source-location // reporting. @@ -61,7 +63,8 @@ impl SpanHandler { self.handler.custom_emit(&*self.cm, sp, msg, Note); } pub fn span_bug(&self, sp: Span, msg: &str) -> ! { - self.span_fatal(sp, ice_msg(msg)); + self.handler.emit(Some((&*self.cm, sp)), msg, Bug); + fail!(ExplicitBug); } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { self.span_bug(sp, ~"unimplemented " + msg); @@ -116,7 +119,8 @@ impl Handler { self.emit.borrow_mut().get().emit(None, msg, Note); } pub fn bug(&self, msg: &str) -> ! { - self.fatal(ice_msg(msg)); + self.emit.borrow_mut().get().emit(None, msg, Bug); + fail!(ExplicitBug); } pub fn unimpl(&self, msg: &str) -> ! { self.bug(~"unimplemented " + msg); @@ -133,11 +137,6 @@ impl Handler { } } -pub fn ice_msg(msg: &str) -> ~str { - format!("internal compiler error: {}\nThis message reflects a bug in the Rust compiler. \ - \nWe would appreciate a bug report: {}", msg, BUG_REPORT_URL) -} - pub fn mk_span_handler(handler: @Handler, cm: @codemap::CodeMap) -> @SpanHandler { @SpanHandler { @@ -159,6 +158,7 @@ pub fn mk_handler(e: ~Emitter) -> @Handler { #[deriving(Eq)] pub enum Level { + Bug, Fatal, Error, Warning, @@ -170,6 +170,7 @@ impl fmt::Show for Level { use std::fmt::Show; match *self { + Bug => "error: internal compiler error".fmt(f), Fatal | Error => "error".fmt(f), Warning => "warning".fmt(f), Note => "note".fmt(f), @@ -180,7 +181,7 @@ impl fmt::Show for Level { impl Level { fn color(self) -> term::color::Color { match self { - Fatal | Error => term::color::BRIGHT_RED, + Bug | Fatal | Error => term::color::BRIGHT_RED, Warning => term::color::BRIGHT_YELLOW, Note => term::color::BRIGHT_GREEN }