Skip to content

Commit d0f6ef0

Browse files
committed
auto merge of #11620 : alexcrichton/rust/rustc-silent, r=brson
This commit re-works how the monitor() function works and how it both receives and transmits errors. There are a few cases in which the compiler can abort: 1. A normal compiler error. In this case, the compiler raises a FatalError as the failure value of the task. If this happens, then the monitor task does nothing. It ignores all stderr output of the child task and it also suppresses the failure message of the main task itself. This means that on a normal compiler error just the error message itself is printed. 2. A normal internal compiler error. These are invoked from sess.span_bug() and friends. In these cases, they follow the same path (raising a FatalError), but they will also print an ICE message which has a URL to go report a bug. 3. An actual compiler bug. This happens whenever anything calls fail!() instead of going through the session itself. In this case, we print out stuff about RUST_LOG=2 and we by default capture all stderr and print via warn!() so it's only printed out with the RUST_LOG var set.
2 parents b5a110c + 2784313 commit d0f6ef0

File tree

2 files changed

+28
-87
lines changed

2 files changed

+28
-87
lines changed

src/librustc/lib.rs

Lines changed: 21 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,16 @@ use middle::lint;
3838

3939
use d = driver::driver;
4040

41-
use std::cast;
42-
use std::comm;
4341
use std::io;
44-
use std::io::Reader;
4542
use std::num;
4643
use std::os;
47-
use std::result;
4844
use std::str;
4945
use std::task;
5046
use std::vec;
5147
use extra::getopts::groups;
5248
use extra::getopts;
5349
use syntax::ast;
5450
use syntax::attr;
55-
use syntax::codemap;
5651
use syntax::diagnostic::Emitter;
5752
use syntax::diagnostic;
5853
use syntax::parse;
@@ -126,21 +121,6 @@ pub mod lib {
126121
pub mod llvmdeps;
127122
}
128123

129-
// A curious inner module that allows ::std::foo to be available in here for
130-
// macros.
131-
/*
132-
mod std {
133-
pub use std::clone;
134-
pub use std::cmp;
135-
pub use std::os;
136-
pub use std::str;
137-
pub use std::sys;
138-
pub use std::to_bytes;
139-
pub use std::unstable;
140-
pub use extra::serialize;
141-
}
142-
*/
143-
144124
pub fn version(argv0: &str) {
145125
let vers = match option_env!("CFG_VERSION") {
146126
Some(vers) => vers,
@@ -344,45 +324,12 @@ fn parse_crate_attrs(sess: session::Session,
344324
}
345325
}
346326

347-
#[deriving(Eq)]
348-
pub enum monitor_msg {
349-
fatal,
350-
done,
351-
}
352-
353-
struct RustcEmitter {
354-
ch_capture: comm::SharedChan<monitor_msg>
355-
}
356-
357-
impl diagnostic::Emitter for RustcEmitter {
358-
fn emit(&self,
359-
cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
360-
msg: &str,
361-
lvl: diagnostic::Level) {
362-
if lvl == diagnostic::Fatal {
363-
let this = unsafe { cast::transmute_mut(self) };
364-
this.ch_capture.send(fatal)
365-
}
366-
367-
diagnostic::DefaultEmitter.emit(cmsp, msg, lvl)
368-
}
369-
}
370-
371-
/*
372-
This is a sanity check that any failure of the compiler is performed
373-
through the diagnostic module and reported properly - we shouldn't be calling
374-
plain-old-fail on any execution path that might be taken. Since we have
375-
console logging off by default, hitting a plain fail statement would make the
376-
compiler silently exit, which would be terrible.
377-
378-
This method wraps the compiler in a subtask and injects a function into the
379-
diagnostic emitter which records when we hit a fatal error. If the task
380-
fails without recording a fatal error then we've encountered a compiler
381-
bug and need to present an error.
382-
*/
327+
/// Run a procedure which will detect failures in the compiler and print nicer
328+
/// error messages rather than just failing the test.
329+
///
330+
/// The diagnostic emitter yielded to the procedure should be used for reporting
331+
/// errors of the compiler.
383332
pub fn monitor(f: proc(@diagnostic::Emitter)) {
384-
use std::comm::*;
385-
386333
// XXX: This is a hack for newsched since it doesn't support split stacks.
387334
// rustc needs a lot of stack! When optimizations are disabled, it needs
388335
// even *more* stack than usual as well.
@@ -391,8 +338,6 @@ pub fn monitor(f: proc(@diagnostic::Emitter)) {
391338
#[cfg(not(rtopt))]
392339
static STACK_SIZE: uint = 20000000; // 20MB
393340

394-
let (p, ch) = SharedChan::new();
395-
let ch_capture = ch.clone();
396341
let mut task_builder = task::task();
397342
task_builder.name("rustc");
398343

@@ -402,30 +347,18 @@ pub fn monitor(f: proc(@diagnostic::Emitter)) {
402347
task_builder.opts.stack_size = Some(STACK_SIZE);
403348
}
404349

405-
match task_builder.try(proc() {
406-
let ch = ch_capture.clone();
407-
// The 'diagnostics emitter'. Every error, warning, etc. should
408-
// go through this function.
409-
let demitter = @RustcEmitter {
410-
ch_capture: ch.clone(),
411-
} as @diagnostic::Emitter;
412-
413-
struct finally {
414-
ch: SharedChan<monitor_msg>,
415-
}
350+
let (p, c) = Chan::new();
351+
let w = io::ChanWriter::new(c);
352+
let mut r = io::PortReader::new(p);
416353

417-
impl Drop for finally {
418-
fn drop(&mut self) { self.ch.send(done); }
419-
}
420-
421-
let _finally = finally { ch: ch };
422-
423-
f(demitter);
354+
match task_builder.try(proc() {
355+
io::stdio::set_stderr(~w as ~io::Writer);
356+
f(@diagnostic::DefaultEmitter)
424357
}) {
425-
result::Ok(_) => { /* fallthrough */ }
426-
result::Err(_) => {
358+
Ok(()) => { /* fallthrough */ }
359+
Err(value) => {
427360
// Task failed without emitting a fatal diagnostic
428-
if p.recv() == done {
361+
if !value.is::<diagnostic::FatalError>() {
429362
diagnostic::DefaultEmitter.emit(
430363
None,
431364
diagnostic::ice_msg("unexpected failure"),
@@ -434,17 +367,20 @@ pub fn monitor(f: proc(@diagnostic::Emitter)) {
434367
let xs = [
435368
~"the compiler hit an unexpected failure path. \
436369
this is a bug",
437-
~"try running with RUST_LOG=rustc=1 \
438-
to get further details and report the results \
439-
to github.com/mozilla/rust/issues"
440370
];
441371
for note in xs.iter() {
442372
diagnostic::DefaultEmitter.emit(None,
443373
*note,
444374
diagnostic::Note)
445375
}
376+
377+
println!("{}", r.read_to_str());
446378
}
447-
// Fail so the process returns a failure code
379+
380+
// Fail so the process returns a failure code, but don't pollute the
381+
// output with some unnecessary failure messages, we've already
382+
// printed everything that we needed to.
383+
io::stdio::set_stderr(~io::util::NullWriter as ~io::Writer);
448384
fail!();
449385
}
450386
}

src/libsyntax/diagnostic.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ pub trait Emitter {
2727
lvl: Level);
2828
}
2929

30+
/// This structure is used to signify that a task has failed with a fatal error
31+
/// from the diagnostics. You can use this with the `Any` trait to figure out
32+
/// how a rustc task died (if so desired).
33+
pub struct FatalError;
34+
3035
// a span-handler is like a handler but also
3136
// accepts span information for source-location
3237
// reporting.
@@ -38,7 +43,7 @@ pub struct SpanHandler {
3843
impl SpanHandler {
3944
pub fn span_fatal(@self, sp: Span, msg: &str) -> ! {
4045
self.handler.emit(Some((&*self.cm, sp)), msg, Fatal);
41-
fail!();
46+
fail!(FatalError);
4247
}
4348
pub fn span_err(@self, sp: Span, msg: &str) {
4449
self.handler.emit(Some((&*self.cm, sp)), msg, Error);
@@ -72,7 +77,7 @@ pub struct Handler {
7277
impl Handler {
7378
pub fn fatal(@self, msg: &str) -> ! {
7479
self.emit.emit(None, msg, Fatal);
75-
fail!();
80+
fail!(FatalError);
7681
}
7782
pub fn err(@self, msg: &str) {
7883
self.emit.emit(None, msg, Error);

0 commit comments

Comments
 (0)