Skip to content

Commit 323dad1

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 7619792 commit 323dad1

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
@@ -424,10 +424,14 @@ pub struct DiagCtxt {
424424
struct DiagCtxtInner {
425425
flags: DiagCtxtFlags,
426426

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

432436
/// The number of stashed errors. Unlike the other counts, this can go up
433437
/// and down, so it doesn't guarantee anything.
@@ -443,8 +447,6 @@ struct DiagCtxtInner {
443447
has_printed: bool,
444448

445449
emitter: Box<DynEmitter>,
446-
delayed_bugs: Vec<DelayedDiagnostic>,
447-
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
448450
/// This flag indicates that an expected diagnostic was emitted and suppressed.
449451
/// This is used for the `good_path_delayed_bugs` check.
450452
suppressed_expected_diag: bool,
@@ -556,7 +558,7 @@ impl Drop for DiagCtxtInner {
556558
fn drop(&mut self) {
557559
self.emit_stashed_diagnostics();
558560

559-
if !self.has_errors() {
561+
if self.err_guars.is_empty() {
560562
self.flush_delayed(DelayedBugKind::Normal)
561563
}
562564

@@ -600,15 +602,15 @@ impl DiagCtxt {
600602
Self {
601603
inner: Lock::new(DiagCtxtInner {
602604
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
603-
lint_err_count: 0,
604-
err_count: 0,
605+
err_guars: Vec::new(),
606+
lint_err_guars: Vec::new(),
607+
delayed_bugs: Vec::new(),
608+
good_path_delayed_bugs: Vec::new(),
605609
stashed_err_count: 0,
606610
deduplicated_err_count: 0,
607611
deduplicated_warn_count: 0,
608612
has_printed: false,
609613
emitter,
610-
delayed_bugs: Vec::new(),
611-
good_path_delayed_bugs: Vec::new(),
612614
suppressed_expected_diag: false,
613615
taught_diagnostics: Default::default(),
614616
emitted_diagnostic_codes: Default::default(),
@@ -657,14 +659,14 @@ impl DiagCtxt {
657659
/// the overall count of emitted error diagnostics.
658660
pub fn reset_err_count(&self) {
659661
let mut inner = self.inner.borrow_mut();
660-
inner.lint_err_count = 0;
661-
inner.err_count = 0;
662662
inner.stashed_err_count = 0;
663663
inner.deduplicated_err_count = 0;
664664
inner.deduplicated_warn_count = 0;
665665
inner.has_printed = false;
666666

667667
// actually free the underlying memory (which `clear` would not do)
668+
inner.err_guars = Default::default();
669+
inner.lint_err_guars = Default::default();
668670
inner.delayed_bugs = Default::default();
669671
inner.good_path_delayed_bugs = Default::default();
670672
inner.taught_diagnostics = Default::default();
@@ -927,7 +929,7 @@ impl DiagCtxt {
927929
/// This excludes lint errors, delayed bugs, and stashed errors.
928930
#[inline]
929931
pub fn err_count(&self) -> usize {
930-
self.inner.borrow().err_count
932+
self.inner.borrow().err_guars.len()
931933
}
932934

933935
/// This excludes normal errors, lint errors and delayed bugs. Unless
@@ -941,36 +943,19 @@ impl DiagCtxt {
941943

942944
/// This excludes lint errors, delayed bugs, and stashed errors.
943945
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
944-
self.inner.borrow().has_errors().then(|| {
945-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
946-
#[allow(deprecated)]
947-
ErrorGuaranteed::unchecked_error_guaranteed()
948-
})
946+
self.inner.borrow().has_errors()
949947
}
950948

951949
/// This excludes delayed bugs and stashed errors. Unless absolutely
952950
/// necessary, prefer `has_errors` to this method.
953951
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
954-
let inner = self.inner.borrow();
955-
let result = inner.has_errors() || inner.lint_err_count > 0;
956-
result.then(|| {
957-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
958-
#[allow(deprecated)]
959-
ErrorGuaranteed::unchecked_error_guaranteed()
960-
})
952+
self.inner.borrow().has_errors_or_lint_errors()
961953
}
962954

963955
/// This excludes stashed errors. Unless absolutely necessary, prefer
964956
/// `has_errors` or `has_errors_or_lint_errors` to this method.
965957
pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
966-
let inner = self.inner.borrow();
967-
let result =
968-
inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty();
969-
result.then(|| {
970-
// FIXME(nnethercote) find a way to store an `ErrorGuaranteed`.
971-
#[allow(deprecated)]
972-
ErrorGuaranteed::unchecked_error_guaranteed()
973-
})
958+
self.inner.borrow().has_errors_or_lint_errors_or_delayed_bugs()
974959
}
975960

976961
pub fn print_error_count(&self, registry: &Registry) {
@@ -1050,7 +1035,7 @@ impl DiagCtxt {
10501035
pub fn abort_if_errors(&self) {
10511036
let mut inner = self.inner.borrow_mut();
10521037
inner.emit_stashed_diagnostics();
1053-
if inner.has_errors() {
1038+
if !inner.err_guars.is_empty() {
10541039
FatalError.raise();
10551040
}
10561041
}
@@ -1170,8 +1155,21 @@ impl DiagCtxt {
11701155
) {
11711156
let mut inner = self.inner.borrow_mut();
11721157

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

@@ -1231,7 +1229,7 @@ impl DiagCtxt {
12311229
impl DiagCtxtInner {
12321230
/// Emit all stashed diagnostics.
12331231
fn emit_stashed_diagnostics(&mut self) {
1234-
let has_errors = self.has_errors();
1232+
let has_errors = !self.err_guars.is_empty();
12351233
for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
12361234
// Decrement the count tracking the stash; emitting will increment it.
12371235
if diag.is_error() {
@@ -1293,9 +1291,13 @@ impl DiagCtxtInner {
12931291
// when an error is first emitted, also), but maybe there's a case
12941292
// in which that's not sound? otherwise this is really inefficient.
12951293
let backtrace = std::backtrace::Backtrace::capture();
1296-
self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
1294+
// This `unchecked_error_guaranteed` is valid. It is where the
1295+
// `ErrorGuaranteed` for delayed bugs originates.
12971296
#[allow(deprecated)]
1298-
return Some(ErrorGuaranteed::unchecked_error_guaranteed());
1297+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1298+
self.delayed_bugs
1299+
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1300+
return Some(guar);
12991301
}
13001302
GoodPathDelayedBug => {
13011303
let backtrace = std::backtrace::Backtrace::capture();
@@ -1329,7 +1331,6 @@ impl DiagCtxtInner {
13291331
!self.emitted_diagnostics.insert(diagnostic_hash)
13301332
};
13311333

1332-
let level = diagnostic.level;
13331334
let is_error = diagnostic.is_error();
13341335
let is_lint = diagnostic.is_lint.is_some();
13351336

@@ -1368,36 +1369,47 @@ impl DiagCtxtInner {
13681369
}
13691370

13701371
if is_error {
1372+
// This `unchecked_error_guaranteed` is valid. It is where the
1373+
// `ErrorGuaranteed` for errors and lint errors originates.
1374+
#[allow(deprecated)]
1375+
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
1376+
guaranteed = Some(guar);
13711377
if is_lint {
1372-
self.lint_err_count += 1;
1378+
self.lint_err_guars.push(guar);
13731379
} else {
1374-
self.err_count += 1;
1380+
self.err_guars.push(guar);
13751381
}
13761382
self.panic_if_treat_err_as_bug();
13771383
}
1378-
1379-
#[allow(deprecated)]
1380-
if level == Level::Error {
1381-
guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed());
1382-
}
13831384
});
13841385

13851386
guaranteed
13861387
}
13871388

13881389
fn treat_err_as_bug(&self) -> bool {
1389-
self.flags.treat_err_as_bug.is_some_and(|c| self.err_count + self.lint_err_count >= c.get())
1390+
self.flags
1391+
.treat_err_as_bug
1392+
.is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() >= c.get())
13901393
}
13911394

13921395
// Use this one before incrementing `err_count`.
13931396
fn treat_next_err_as_bug(&self) -> bool {
13941397
self.flags
13951398
.treat_err_as_bug
1396-
.is_some_and(|c| self.err_count + self.lint_err_count + 1 >= c.get())
1399+
.is_some_and(|c| self.err_guars.len() + self.lint_err_guars.len() + 1 >= c.get())
1400+
}
1401+
1402+
fn has_errors(&self) -> Option<ErrorGuaranteed> {
1403+
self.err_guars.get(0).copied()
1404+
}
1405+
1406+
fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
1407+
self.has_errors().or_else(|| self.lint_err_guars.get(0).copied())
13971408
}
13981409

1399-
fn has_errors(&self) -> bool {
1400-
self.err_count > 0
1410+
fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
1411+
self.has_errors_or_lint_errors()
1412+
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
14011413
}
14021414

14031415
fn failure_note(&mut self, msg: impl Into<DiagnosticMessage>) {
@@ -1407,7 +1419,7 @@ impl DiagCtxtInner {
14071419
fn flush_delayed(&mut self, kind: DelayedBugKind) {
14081420
let (bugs, note1) = match kind {
14091421
DelayedBugKind::Normal => (
1410-
std::mem::take(&mut self.delayed_bugs),
1422+
std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(),
14111423
"no errors encountered even though delayed bugs were created",
14121424
),
14131425
DelayedBugKind::GoodPath => (
@@ -1472,7 +1484,7 @@ impl DiagCtxtInner {
14721484
fn panic_if_treat_err_as_bug(&self) {
14731485
if self.treat_err_as_bug() {
14741486
let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
1475-
assert_eq!(n, self.err_count + self.lint_err_count);
1487+
assert_eq!(n, self.err_guars.len() + self.lint_err_guars.len());
14761488
if n == 1 {
14771489
panic!("aborting due to `-Z treat-err-as-bug=1`");
14781490
} else {

0 commit comments

Comments
 (0)