Skip to content

Commit e5df8a6

Browse files
committed
Remove final unwanted unchecked_error_guaranteed calls.
Now that error counts can't go up and down due to stashing/stealing, we have a nice property: (err_count > 0) iff (an ErrorGuaranteed has been produced) So we can now record `ErrorGuaranteed`s within `DiagCtxt` and use that in methods like `has_error`, instead of checking that the count is greater than 0 and calling `unchecked_error_guaranteed` to create the `ErrorGuaranteed`. In fact, we can record a `Vec<ErrorGuaranteed>` and use its length to count the number, instead of maintaining a separate count.
1 parent f4cfd87 commit e5df8a6

File tree

1 file changed

+65
-53
lines changed
  • compiler/rustc_errors/src

1 file changed

+65
-53
lines changed

compiler/rustc_errors/src/lib.rs

Lines changed: 65 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -428,10 +428,14 @@ pub struct DiagCtxt {
428428
struct DiagCtxtInner {
429429
flags: DiagCtxtFlags,
430430

431-
/// The number of lint errors that have been emitted, including duplicates.
432-
lint_err_count: usize,
433-
/// The number of non-lint errors that have been emitted, including duplicates.
434-
err_count: usize,
431+
/// The error guarantees from all emitted errors. The length gives the error count.
432+
err_guars: Vec<ErrorGuaranteed>,
433+
/// The error guarantee from all emitted lint errors. The length gives the
434+
/// lint error count.
435+
lint_err_guars: Vec<ErrorGuaranteed>,
436+
/// The delayed bugs and their error guarantees.
437+
delayed_bugs: Vec<(DelayedDiagnostic, ErrorGuaranteed)>,
438+
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
435439

436440
/// The number of stashed errors. Unlike the other counts, this can go up
437441
/// and down, so it doesn't guarantee anything.
@@ -447,8 +451,6 @@ struct DiagCtxtInner {
447451
has_printed: bool,
448452

449453
emitter: Box<DynEmitter>,
450-
delayed_bugs: Vec<DelayedDiagnostic>,
451-
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
452454
/// This flag indicates that an expected diagnostic was emitted and suppressed.
453455
/// This is used for the `good_path_delayed_bugs` check.
454456
suppressed_expected_diag: bool,
@@ -560,7 +562,7 @@ impl Drop for DiagCtxtInner {
560562
fn drop(&mut self) {
561563
self.emit_stashed_diagnostics();
562564

563-
if !self.has_errors() {
565+
if self.err_guars.is_empty() {
564566
self.flush_delayed(DelayedBugKind::Normal)
565567
}
566568

@@ -604,15 +606,15 @@ impl DiagCtxt {
604606
Self {
605607
inner: Lock::new(DiagCtxtInner {
606608
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
607-
lint_err_count: 0,
608-
err_count: 0,
609+
err_guars: Vec::new(),
610+
lint_err_guars: Vec::new(),
611+
delayed_bugs: Vec::new(),
612+
good_path_delayed_bugs: Vec::new(),
609613
stashed_err_count: 0,
610614
deduplicated_err_count: 0,
611615
deduplicated_warn_count: 0,
612616
has_printed: false,
613617
emitter,
614-
delayed_bugs: Vec::new(),
615-
good_path_delayed_bugs: Vec::new(),
616618
suppressed_expected_diag: false,
617619
taught_diagnostics: Default::default(),
618620
emitted_diagnostic_codes: Default::default(),
@@ -661,14 +663,14 @@ impl DiagCtxt {
661663
/// the overall count of emitted error diagnostics.
662664
pub fn reset_err_count(&self) {
663665
let mut inner = self.inner.borrow_mut();
664-
inner.lint_err_count = 0;
665-
inner.err_count = 0;
666666
inner.stashed_err_count = 0;
667667
inner.deduplicated_err_count = 0;
668668
inner.deduplicated_warn_count = 0;
669669
inner.has_printed = false;
670670

671671
// actually free the underlying memory (which `clear` would not do)
672+
inner.err_guars = Default::default();
673+
inner.lint_err_guars = Default::default();
672674
inner.delayed_bugs = Default::default();
673675
inner.good_path_delayed_bugs = Default::default();
674676
inner.taught_diagnostics = Default::default();
@@ -932,7 +934,7 @@ impl DiagCtxt {
932934
/// This excludes lint errors, delayed bugs, and stashed errors.
933935
#[inline]
934936
pub fn err_count(&self) -> usize {
935-
self.inner.borrow().err_count
937+
self.inner.borrow().err_guars.len()
936938
}
937939

938940
/// This excludes normal errors, lint errors and delayed bugs. Unless
@@ -946,36 +948,19 @@ impl DiagCtxt {
946948

947949
/// This excludes lint errors, delayed bugs, and stashed errors.
948950
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
949-
self.inner.borrow().has_errors().then(|| {
950-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
951-
#[allow(deprecated)]
952-
ErrorGuaranteed::unchecked_error_guaranteed()
953-
})
951+
self.inner.borrow().has_errors()
954952
}
955953

956954
/// This excludes delayed bugs and stashed errors. Unless absolutely
957955
/// necessary, prefer `has_errors` to this method.
958956
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
959-
let inner = self.inner.borrow();
960-
let result = inner.has_errors() || inner.lint_err_count > 0;
961-
result.then(|| {
962-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
963-
#[allow(deprecated)]
964-
ErrorGuaranteed::unchecked_error_guaranteed()
965-
})
957+
self.inner.borrow().has_errors_or_lint_errors()
966958
}
967959

968960
/// This excludes stashed errors. Unless absolutely necessary, prefer
969961
/// `has_errors` or `has_errors_or_lint_errors` to this method.
970962
pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
971-
let inner = self.inner.borrow();
972-
let result =
973-
inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty();
974-
result.then(|| {
975-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
976-
#[allow(deprecated)]
977-
ErrorGuaranteed::unchecked_error_guaranteed()
978-
})
963+
self.inner.borrow().has_errors_or_lint_errors_or_delayed_bugs()
979964
}
980965

981966
pub fn print_error_count(&self, registry: &Registry) {
@@ -1055,7 +1040,7 @@ impl DiagCtxt {
10551040
pub fn abort_if_errors(&self) {
10561041
let mut inner = self.inner.borrow_mut();
10571042
inner.emit_stashed_diagnostics();
1058-
if inner.has_errors() {
1043+
if !inner.err_guars.is_empty() {
10591044
FatalError.raise();
10601045
}
10611046
}
@@ -1175,8 +1160,21 @@ impl DiagCtxt {
11751160
) {
11761161
let mut inner = self.inner.borrow_mut();
11771162

1163+
// This "error" is an odd duck.
1164+
// - It's only produce with JSON output.
1165+
// - It's not emitted the usual way, via `emit_diagnostic`.
1166+
// - The `$message_type` field is "unused_externs" rather than the usual
1167+
// "diagnosic".
1168+
//
1169+
// We count it as a lint error because it has a lint level. The value
1170+
// of `loud` (which comes from "unused-externs" or
1171+
// "unused-externs-silent"), also affects whether it's treated like a
1172+
// hard error or not.
11781173
if loud && lint_level.is_error() {
1179-
inner.lint_err_count += 1;
1174+
// This `unchecked_error_guaranteed` is valid. It is where the
1175+
// `ErrorGuaranteed` for unused_extern errors originates.
1176+
#[allow(deprecated)]
1177+
inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed());
11801178
inner.panic_if_treat_err_as_bug();
11811179
}
11821180

@@ -1236,7 +1234,7 @@ impl DiagCtxt {
12361234
impl DiagCtxtInner {
12371235
/// Emit all stashed diagnostics.
12381236
fn emit_stashed_diagnostics(&mut self) {
1239-
let has_errors = self.has_errors();
1237+
let has_errors = !self.err_guars.is_empty();
12401238
for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
12411239
// Decrement the count tracking the stash; emitting will increment it.
12421240
if diag.is_error() {
@@ -1298,9 +1296,13 @@ impl DiagCtxtInner {
12981296
// when an error is first emitted, also), but maybe there's a case
12991297
// in which that's not sound? otherwise this is really inefficient.
13001298
let backtrace = std::backtrace::Backtrace::capture();
1301-
self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
1299+
// This `unchecked_error_guaranteed` is valid. It is where the
1300+
// `ErrorGuaranteed` for delayed bugs originates.
13021301
#[allow(deprecated)]
1303-
return Some(ErrorGuaranteed::unchecked_error_guaranteed());
1302+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1303+
self.delayed_bugs
1304+
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1305+
return Some(guar);
13041306
}
13051307
GoodPathDelayedBug => {
13061308
let backtrace = std::backtrace::Backtrace::capture();
@@ -1334,7 +1336,6 @@ impl DiagCtxtInner {
13341336
!self.emitted_diagnostics.insert(diagnostic_hash)
13351337
};
13361338

1337-
let level = diagnostic.level;
13381339
let is_error = diagnostic.is_error();
13391340
let is_lint = diagnostic.is_lint.is_some();
13401341

@@ -1373,36 +1374,47 @@ impl DiagCtxtInner {
13731374
}
13741375

13751376
if is_error {
1377+
// This `unchecked_error_guaranteed` is valid. It is where the
1378+
// `ErrorGuaranteed` for errors and lint errors originates.
1379+
#[allow(deprecated)]
1380+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1381+
guaranteed = Some(guar);
13761382
if is_lint {
1377-
self.lint_err_count += 1;
1383+
self.lint_err_guars.push(guar);
13781384
} else {
1379-
self.err_count += 1;
1385+
self.err_guars.push(guar);
13801386
}
13811387
self.panic_if_treat_err_as_bug();
13821388
}
1383-
1384-
#[allow(deprecated)]
1385-
if level == Level::Error {
1386-
guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed());
1387-
}
13881389
});
13891390

13901391
guaranteed
13911392
}
13921393

13931394
fn treat_err_as_bug(&self) -> bool {
1394-
self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get())
1395+
self.flags
1396+
.treat_err_as_bug
1397+
.is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
13951398
}
13961399

13971400
// Use this one before incrementing `err_count`.
13981401
fn treat_next_err_as_bug(&self) -> bool {
13991402
self.flags
14001403
.treat_err_as_bug
1401-
.is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get())
1404+
.is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1405+
}
1406+
1407+
fn has_errors(&self) -> Option<ErrorGuaranteed> {
1408+
self.err_guars.get(0).copied()
1409+
}
1410+
1411+
fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
1412+
self.has_errors().or_else(|| self.lint_err_guars.get(0).copied())
14021413
}
14031414

1404-
fn has_errors(&self) -> bool {
1405-
self.err_count > 0
1415+
fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1416+
self.has_errors_or_lint_errors()
1417+
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
14061418
}
14071419

14081420
fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
@@ -1412,7 +1424,7 @@ impl DiagCtxtInner {
14121424
fn flush_delayed(&mut self, kind: DelayedBugKind) {
14131425
let (bugs, note1) = match kind {
14141426
DelayedBugKind::Normal => (
1415-
std::mem::take(&mut self.delayed_bugs),
1427+
std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(),
14161428
"no errors encountered even though delayed bugs were created",
14171429
),
14181430
DelayedBugKind::GoodPath => (
@@ -1477,7 +1489,7 @@ impl DiagCtxtInner {
14771489
fn panic_if_treat_err_as_bug(&self) {
14781490
if self.treat_err_as_bug() {
14791491
let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1480-
assert_eq!(n, self.err_count + self.lint_err_count);
1492+
assert_eq!(n, self.err_guars.len() + self.lint_err_guars.len());
14811493
if n == 1 {
14821494
panic!("aborting due to `-Z treat-err-as-bug=1`");
14831495
} else {

0 commit comments

Comments
 (0)