diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 774ab0333db5..dfd8e4dd571b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1234,7 +1234,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "parse only; do not compile, assemble, or link"), no_codegen: bool = (false, parse_bool, [TRACKED], "run all passes except codegen; no output"), - treat_err_as_bug: bool = (false, parse_bool, [TRACKED], + treat_err_as_bug: Option = (None, parse_opt_uint, [TRACKED], "treat all errors that occur as bugs"), report_delayed_bugs: bool = (false, parse_bool, [TRACKED], "immediately print bugs registered with `delay_span_bug`"), @@ -3212,7 +3212,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.debugging_opts.treat_err_as_bug = true; + opts.debugging_opts.treat_err_as_bug = Some(1); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 774bc8b450b5..751fa7e95e3a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1315,7 +1315,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { Box::new(EmitterWriter::stderr(color_config, None, true, false)) } }; - let handler = errors::Handler::with_emitter(true, false, emitter); + let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal); errors::FatalError.raise(); } @@ -1330,7 +1330,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) { Box::new(EmitterWriter::stderr(color_config, None, true, false)) } }; - let handler = errors::Handler::with_emitter(true, false, emitter); + let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 4bccc2a6d1f7..c84b38cde818 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -247,7 +247,7 @@ pub struct CodegenContext { impl CodegenContext { pub fn create_diag_handler(&self) -> Handler { - Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone())) + Handler::with_emitter(true, None, Box::new(self.diag_emitter.clone())) } pub fn config(&self, kind: ModuleKind) -> &ModuleConfig { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index cc1b8916c107..656d8e463dbd 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -148,7 +148,7 @@ pub fn run(run_compiler: F) -> isize true, false ); - let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); + let handler = errors::Handler::with_emitter(true, None, Box::new(emitter)); handler.emit(&MultiSpan::new(), "aborting due to previous error(s)", errors::Level::Fatal); @@ -1327,7 +1327,7 @@ pub fn monitor(f: F) -> Result<(), CompilationFail None, false, false)); - let handler = errors::Handler::with_emitter(true, false, emitter); + let handler = errors::Handler::with_emitter(true, None, emitter); // a .span_bug or .bug call has already printed what // it wants to print. diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 0c808a07f9ba..a995d808bc41 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -103,7 +103,7 @@ impl<'a> DiagnosticBuilder<'a> { /// Buffers the diagnostic for later emission, unless handler /// has disabled such buffering. pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { - if self.handler.flags.dont_buffer_diagnostics || self.handler.flags.treat_err_as_bug { + if self.handler.flags.dont_buffer_diagnostics || self.handler.treat_err_as_bug() { self.emit(); return; } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 87b475152683..ae634018b935 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -330,7 +330,7 @@ pub struct HandlerFlags { pub can_emit_warnings: bool, /// If true, error-level diagnostics are upgraded to bug-level. /// (rustc: see `-Z treat-err-as-bug`) - pub treat_err_as_bug: bool, + pub treat_err_as_bug: Option, /// If true, immediately emit diagnostics that would otherwise be buffered. /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`) pub dont_buffer_diagnostics: bool, @@ -360,7 +360,7 @@ impl Drop for Handler { impl Handler { pub fn with_tty_emitter(color_config: ColorConfig, can_emit_warnings: bool, - treat_err_as_bug: bool, + treat_err_as_bug: Option, cm: Option>) -> Handler { Handler::with_tty_emitter_and_flags( @@ -382,7 +382,7 @@ impl Handler { } pub fn with_emitter(can_emit_warnings: bool, - treat_err_as_bug: bool, + treat_err_as_bug: Option, e: Box) -> Handler { Handler::with_emitter_and_flags( @@ -516,7 +516,7 @@ impl Handler { } fn panic_if_treat_err_as_bug(&self) { - if self.flags.treat_err_as_bug { + if self.treat_err_as_bug() { panic!("encountered error with `-Z treat_err_as_bug"); } } @@ -558,7 +558,7 @@ impl Handler { panic!(ExplicitBug); } pub fn delay_span_bug>(&self, sp: S, msg: &str) { - if self.flags.treat_err_as_bug { + if self.treat_err_as_bug() { // FIXME: don't abort here if report_delayed_bugs is off self.span_bug(sp, msg); } @@ -593,14 +593,14 @@ impl Handler { DiagnosticBuilder::new(self, FailureNote, msg).emit() } pub fn fatal(&self, msg: &str) -> FatalError { - if self.flags.treat_err_as_bug { + if self.treat_err_as_bug() { self.bug(msg); } DiagnosticBuilder::new(self, Fatal, msg).emit(); FatalError } pub fn err(&self, msg: &str) { - if self.flags.treat_err_as_bug { + if self.treat_err_as_bug() { self.bug(msg); } let mut db = DiagnosticBuilder::new(self, Error, msg); @@ -610,6 +610,9 @@ impl Handler { let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } + fn treat_err_as_bug(&self) -> bool { + self.flags.treat_err_as_bug.map(|c| self.err_count() >= c).unwrap_or(false) + } pub fn note_without_error(&self, msg: &str) { let mut db = DiagnosticBuilder::new(self, Note, msg); db.emit(); @@ -624,8 +627,8 @@ impl Handler { } fn bump_err_count(&self) { - self.panic_if_treat_err_as_bug(); self.err_count.fetch_add(1, SeqCst); + self.panic_if_treat_err_as_bug(); } pub fn err_count(&self) -> usize { @@ -643,7 +646,13 @@ impl Handler { _ => format!("aborting due to {} previous errors", self.err_count()) }; - let _ = self.fatal(&s); + let _ = if self.treat_err_as_bug() { + self.fatal(&s) + } else { + // only emit one backtrace when using `-Z treat-err-as-bug=X` + DiagnosticBuilder::new(self, Fatal, &s).emit(); + FatalError + }; let can_show_explain = self.emitter.borrow().should_show_explain(); let are_there_diagnostics = !self.emitted_diagnostic_codes.borrow().is_empty(); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index fdb071638b79..f4074bcdba6f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -266,7 +266,7 @@ impl DocAccessLevels for AccessLevels { /// will be created for the handler. pub fn new_handler(error_format: ErrorOutputType, source_map: Option>, - treat_err_as_bug: bool, + treat_err_as_bug: Option, ui_testing: bool, ) -> errors::Handler { // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index b2d4d97d57d8..9cfcfcd6241a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -53,7 +53,7 @@ impl ParseSess { let cm = Lrc::new(SourceMap::new(file_path_mapping)); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, - false, + None, Some(cm.clone())); ParseSess::with_span_handler(handler, cm) }