"run all passes except codegen; no output"),
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
"treat all errors that occur as bugs"),
+ report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
+ "immediately print bugs registered with `delay_span_bug`"),
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces even for non-local macros"),
teach: bool = (false, parse_bool, [TRACKED],
opts.debugging_opts.treat_err_as_bug = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+ opts = reference.clone();
+ opts.debugging_opts.report_delayed_bugs = true;
+ assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
opts = reference.clone();
opts.debugging_opts.continue_parse_after_error = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
err_count: AtomicUsize,
emitter: Lock<Box<dyn Emitter + sync::Send>>,
continue_after_error: LockCell<bool>,
- delayed_span_bug: Lock<Option<Diagnostic>>,
+ delayed_span_bug: Lock<Vec<Diagnostic>>,
// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
// emitting the same diagnostic with extended help (`--teach`) twice, which
pub struct HandlerFlags {
pub can_emit_warnings: bool,
pub treat_err_as_bug: bool,
+ pub report_delayed_bugs: bool,
pub external_macro_backtrace: bool,
}
+impl Drop for Handler {
+ fn drop(&mut self) {
+ if self.err_count() == 0 {
+ let mut bugs = self.delayed_span_bug.borrow_mut();
+ let has_bugs = !bugs.is_empty();
+ for bug in bugs.drain(..) {
+ DiagnosticBuilder::new_diagnostic(self, bug).emit();
+ }
+ if has_bugs {
+ panic!("no errors encountered even though `delay_span_bug` issued");
+ }
+ }
+ }
+}
+
impl Handler {
pub fn with_tty_emitter(color_config: ColorConfig,
can_emit_warnings: bool,
err_count: AtomicUsize::new(0),
emitter: Lock::new(e),
continue_after_error: LockCell::new(true),
- delayed_span_bug: Lock::new(None),
+ delayed_span_bug: Lock::new(Vec::new()),
taught_diagnostics: Lock::new(FxHashSet()),
emitted_diagnostic_codes: Lock::new(FxHashSet()),
emitted_diagnostics: Lock::new(FxHashSet()),
}
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
if self.flags.treat_err_as_bug {
+ // FIXME: don't abort here if report_delayed_bugs is off
self.span_bug(sp, msg);
}
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
diagnostic.set_span(sp.into());
- *self.delayed_span_bug.borrow_mut() = Some(diagnostic);
+ self.delay_as_bug(diagnostic);
+ }
+ fn delay_as_bug(&self, diagnostic: Diagnostic) {
+ if self.flags.report_delayed_bugs {
+ DiagnosticBuilder::new_diagnostic(self, diagnostic.clone()).emit();
+ }
+ self.delayed_span_bug.borrow_mut().push(diagnostic);
}
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Bug);
pub fn abort_if_errors(&self) {
if self.err_count() == 0 {
- if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
- DiagnosticBuilder::new_diagnostic(self, bug).emit();
- }
return;
}
FatalError.raise();