Skip to content

Commit bad2cb0

Browse files
authored
Rollup merge of #121015 - nnethercote:opt-delayed-bug, r=oli-obk
Optimize `delayed_bug` handling. Once we have emitted at least one error, delayed bugs won't be used. So we can (a) we can (a) discard any existing delayed bugs, and (b) stop recording any new delayed bugs. This eliminates a longstanding `FIXME` comment. There should be no soundness issues because it's not possible to un-emit an error. r? `@oli-obk`
2 parents f3e66ed + 71f2e3a commit bad2cb0

File tree

1 file changed

+27
-12
lines changed
  • compiler/rustc_errors/src

1 file changed

+27
-12
lines changed

compiler/rustc_errors/src/lib.rs

+27-12
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,9 @@ impl DiagCtxtInner {
13151315
self.future_breakage_diagnostics.push(diagnostic.clone());
13161316
}
13171317

1318+
// Note that because this comes before the `match` below,
1319+
// `-Zeagerly-emit-delayed-bugs` continues to work even after we've
1320+
// issued an error and stopped recording new delayed bugs.
13181321
if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
13191322
diagnostic.level = Error;
13201323
}
@@ -1326,18 +1329,20 @@ impl DiagCtxtInner {
13261329
diagnostic.level = Bug;
13271330
}
13281331
DelayedBug => {
1329-
// FIXME(eddyb) this should check for `has_errors` and stop pushing
1330-
// once *any* errors were emitted (and truncate `delayed_bugs`
1331-
// when an error is first emitted, also), but maybe there's a case
1332-
// in which that's not sound? otherwise this is really inefficient.
1333-
let backtrace = std::backtrace::Backtrace::capture();
1334-
// This `unchecked_error_guaranteed` is valid. It is where the
1335-
// `ErrorGuaranteed` for delayed bugs originates.
1336-
#[allow(deprecated)]
1337-
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1338-
self.delayed_bugs
1339-
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1340-
return Some(guar);
1332+
// If we have already emitted at least one error, we don't need
1333+
// to record the delayed bug, because it'll never be used.
1334+
return if let Some(guar) = self.has_errors_or_lint_errors() {
1335+
Some(guar)
1336+
} else {
1337+
let backtrace = std::backtrace::Backtrace::capture();
1338+
// This `unchecked_error_guaranteed` is valid. It is where the
1339+
// `ErrorGuaranteed` for delayed bugs originates.
1340+
#[allow(deprecated)]
1341+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1342+
self.delayed_bugs
1343+
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1344+
Some(guar)
1345+
};
13411346
}
13421347
Warning if !self.flags.can_emit_warnings => {
13431348
if diagnostic.has_future_breakage() {
@@ -1403,6 +1408,16 @@ impl DiagCtxtInner {
14031408
}
14041409

14051410
if is_error {
1411+
// If we have any delayed bugs recorded, we can discard them
1412+
// because they won't be used. (This should only occur if there
1413+
// have been no errors previously emitted, because we don't add
1414+
// new delayed bugs once the first error is emitted.)
1415+
if !self.delayed_bugs.is_empty() {
1416+
assert_eq!(self.lint_err_guars.len() + self.err_guars.len(), 0);
1417+
self.delayed_bugs.clear();
1418+
self.delayed_bugs.shrink_to_fit();
1419+
}
1420+
14061421
// This `unchecked_error_guaranteed` is valid. It is where the
14071422
// `ErrorGuaranteed` for errors and lint errors originates.
14081423
#[allow(deprecated)]

0 commit comments

Comments
 (0)