Rollup merge of #58984 - estebank:multi-treat-err-as-bug, r=oli-obk
Teach `-Z treat-err-as-bug` to take a number of errors to emit `-Z treat-err-as-bug` will cause `rustc` to panic after the first error is reported, like previously. `-Z treat-err-as-bug=2` will cause `rustc` to panic after 2 errors have been reported. Fix #58983.
This commit is contained in:
commit
72d4c1ed67
13 changed files with 56 additions and 27 deletions
|
@ -816,6 +816,8 @@ macro_rules! options {
|
|||
Some("crate=integer");
|
||||
pub const parse_unpretty: Option<&str> =
|
||||
Some("`string` or `string=string`");
|
||||
pub const parse_treat_err_as_bug: Option<&str> =
|
||||
Some("either no value or a number bigger than 0");
|
||||
pub const parse_lto: Option<&str> =
|
||||
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
|
||||
`fat`, or omitted");
|
||||
|
@ -1022,6 +1024,13 @@ macro_rules! options {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_treat_err_as_bug(slot: &mut Option<usize>, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some(s) => { *slot = s.parse().ok().filter(|&x| x != 0); slot.unwrap_or(0) != 0 }
|
||||
None => { *slot = Some(1); true }
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
|
||||
if v.is_some() {
|
||||
let mut bool_arg = None;
|
||||
|
@ -1236,8 +1245,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"load proc macros for both target and host, but only link to the target"),
|
||||
no_codegen: bool = (false, parse_bool, [TRACKED],
|
||||
"run all passes except codegen; no output"),
|
||||
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
|
||||
"treat all errors that occur as bugs"),
|
||||
treat_err_as_bug: Option<usize> = (None, parse_treat_err_as_bug, [TRACKED],
|
||||
"treat error number `val` that occurs as bug"),
|
||||
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
|
||||
"immediately print bugs registered with `delay_span_bug`"),
|
||||
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
|
||||
|
@ -3214,7 +3223,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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
|||
|
||||
impl<B: WriteBackendMethods> CodegenContext<B> {
|
||||
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 {
|
||||
|
|
|
@ -148,7 +148,7 @@ pub fn run<F>(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: FnOnce() + Send + 'static>(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.
|
||||
|
|
|
@ -113,7 +113,7 @@ fn test_env_with_pool<F>(
|
|||
) where
|
||||
F: FnOnce(Env),
|
||||
{
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, None, emitter);
|
||||
let sess = session::build_session_(
|
||||
options,
|
||||
None,
|
||||
|
|
|
@ -103,7 +103,9 @@ 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<Diagnostic>) {
|
||||
if self.handler.flags.dont_buffer_diagnostics || self.handler.flags.treat_err_as_bug {
|
||||
if self.handler.flags.dont_buffer_diagnostics ||
|
||||
self.handler.flags.treat_err_as_bug.is_some()
|
||||
{
|
||||
self.emit();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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<usize>,
|
||||
/// 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<usize>,
|
||||
cm: Option<Lrc<SourceMapperDyn>>)
|
||||
-> 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<usize>,
|
||||
e: Box<dyn Emitter + sync::Send>)
|
||||
-> Handler {
|
||||
Handler::with_emitter_and_flags(
|
||||
|
@ -516,8 +516,20 @@ impl Handler {
|
|||
}
|
||||
|
||||
fn panic_if_treat_err_as_bug(&self) {
|
||||
if self.flags.treat_err_as_bug {
|
||||
panic!("encountered error with `-Z treat_err_as_bug");
|
||||
if self.treat_err_as_bug() {
|
||||
let s = match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) {
|
||||
(0, _) => return,
|
||||
(1, 1) => "aborting due to `-Z treat-err-as-bug=1`".to_string(),
|
||||
(1, _) => return,
|
||||
(count, as_bug) => {
|
||||
format!(
|
||||
"aborting after {} errors due to `-Z treat-err-as-bug={}`",
|
||||
count,
|
||||
as_bug,
|
||||
)
|
||||
}
|
||||
};
|
||||
panic!(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,7 +570,7 @@ impl Handler {
|
|||
panic!(ExplicitBug);
|
||||
}
|
||||
pub fn delay_span_bug<S: Into<MultiSpan>>(&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 +605,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 +622,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 +639,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 {
|
||||
|
@ -642,6 +657,9 @@ impl Handler {
|
|||
1 => "aborting due to previous error".to_string(),
|
||||
_ => format!("aborting due to {} previous errors", self.err_count())
|
||||
};
|
||||
if self.treat_err_as_bug() {
|
||||
return;
|
||||
}
|
||||
|
||||
let _ = self.fatal(&s);
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ impl DocAccessLevels for AccessLevels<DefId> {
|
|||
/// will be created for the handler.
|
||||
pub fn new_handler(error_format: ErrorOutputType,
|
||||
source_map: Option<Lrc<source_map::SourceMap>>,
|
||||
treat_err_as_bug: bool,
|
||||
treat_err_as_bug: Option<usize>,
|
||||
ui_testing: bool,
|
||||
) -> errors::Handler {
|
||||
// rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
|
||||
|
|
|
@ -67,7 +67,7 @@ pub fn run(mut options: Options) -> isize {
|
|||
let source_map = Lrc::new(SourceMap::new(sessopts.file_path_mapping()));
|
||||
let handler =
|
||||
errors::Handler::with_tty_emitter(ColorConfig::Auto,
|
||||
true, false,
|
||||
true, None,
|
||||
Some(source_map.clone()));
|
||||
|
||||
let mut sess = session::build_session_(
|
||||
|
@ -272,7 +272,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
|
|||
false);
|
||||
|
||||
// Compile the code
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, None, box emitter);
|
||||
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, None, diagnostic_handler, source_map, Default::default(),
|
||||
|
@ -424,7 +424,7 @@ pub fn make_test(s: &str,
|
|||
// send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
|
||||
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let emitter = EmitterWriter::new(box io::sink(), None, false, false);
|
||||
let handler = Handler::with_emitter(false, false, box emitter);
|
||||
let handler = Handler::with_emitter(false, None, box emitter);
|
||||
let sess = ParseSess::with_span_handler(handler, cm);
|
||||
|
||||
let mut found_main = false;
|
||||
|
|
|
@ -1920,7 +1920,7 @@ mod tests {
|
|||
false,
|
||||
false);
|
||||
ParseSess {
|
||||
span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
|
||||
span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)),
|
||||
unstable_features: UnstableFeatures::from_environment(),
|
||||
config: CrateConfig::default(),
|
||||
included_mod_stack: Lock::new(Vec::new()),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
|||
Some(source_map.clone()),
|
||||
false,
|
||||
false);
|
||||
let handler = Handler::with_emitter(true, false, Box::new(emitter));
|
||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
||||
handler.span_err(msp, "foo");
|
||||
|
||||
assert!(expected_output.chars().next() == Some('\n'),
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
all:
|
||||
$(RUSTC) err.rs -Z treat-err-as-bug 2>&1 \
|
||||
| $(CGREP) "panicked at 'encountered error with \`-Z treat_err_as_bug'"
|
||||
| $(CGREP) "panicked at 'aborting due to \`-Z treat-err-as-bug=1\`'"
|
||||
|
|
Loading…
Add table
Reference in a new issue