Skip to content

Commit f484cf9

Browse files
committed
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.
1 parent 51be29d commit f484cf9

File tree

1 file changed

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

1 file changed

+27
-12
lines changed

Diff for: compiler/rustc_errors/src/lib.rs

+27-12
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,9 @@ impl DiagCtxtInner {
12751275
self.future_breakage_diagnostics.push(diagnostic.clone());
12761276
}
12771277

1278+
// Note that because this comes before the `match` below,
1279+
// `-Zeagerly-emit-delayed-bugs` continues to work even after we've
1280+
// issued an error and stopped recording new delayed bugs.
12781281
if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
12791282
diagnostic.level = Error;
12801283
}
@@ -1286,18 +1289,20 @@ impl DiagCtxtInner {
12861289
diagnostic.level = Bug;
12871290
}
12881291
DelayedBug => {
1289-
// FIXME(eddyb) this should check for `has_errors` and stop pushing
1290-
// once *any* errors were emitted (and truncate `delayed_bugs`
1291-
// when an error is first emitted, also), but maybe there's a case
1292-
// in which that's not sound? otherwise this is really inefficient.
1293-
let backtrace = std::backtrace::Backtrace::capture();
1294-
// This `unchecked_error_guaranteed` is valid. It is where the
1295-
// `ErrorGuaranteed` for delayed bugs originates.
1296-
#[allow(deprecated)]
1297-
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1298-
self.delayed_bugs
1299-
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1300-
return Some(guar);
1292+
// If we have already emitted at least one error, we don't need
1293+
// to record the delayed bug, because it'll never be used.
1294+
return if let Some(guar) = self.has_errors_or_lint_errors() {
1295+
Some(guar)
1296+
} else {
1297+
let backtrace = std::backtrace::Backtrace::capture();
1298+
// This `unchecked_error_guaranteed` is valid. It is where the
1299+
// `ErrorGuaranteed` for delayed bugs originates.
1300+
#[allow(deprecated)]
1301+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1302+
self.delayed_bugs
1303+
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1304+
Some(guar)
1305+
};
13011306
}
13021307
Warning if !self.flags.can_emit_warnings => {
13031308
if diagnostic.has_future_breakage() {
@@ -1363,6 +1368,16 @@ impl DiagCtxtInner {
13631368
}
13641369

13651370
if is_error {
1371+
// If we have any delayed bugs recorded, we can discard them
1372+
// because they won't be used. (This should only occur if there
1373+
// have been no errors previously emitted, because we don't add
1374+
// new delayed bugs once the first error is emitted.)
1375+
if !self.delayed_bugs.is_empty() {
1376+
assert_eq!(self.lint_err_guars.len() + self.err_guars.len(), 0);
1377+
self.delayed_bugs.clear();
1378+
self.delayed_bugs.shrink_to_fit();
1379+
}
1380+
13661381
// This `unchecked_error_guaranteed` is valid. It is where the
13671382
// `ErrorGuaranteed` for errors and lint errors originates.
13681383
#[allow(deprecated)]

0 commit comments

Comments
 (0)