@@ -435,7 +435,6 @@ struct DiagCtxtInner {
435
435
lint_err_guars: Vec<ErrorGuaranteed>,
436
436
/// The delayed bugs and their error guarantees.
437
437
delayed_bugs: Vec<(DelayedDiagnostic, ErrorGuaranteed)>,
438
- good_path_delayed_bugs: Vec<DelayedDiagnostic>,
439
438
440
439
/// The number of stashed errors. Unlike the other counts, this can go up
441
440
/// and down, so it doesn't guarantee anything.
@@ -446,13 +445,18 @@ struct DiagCtxtInner {
446
445
/// The warning count shown to the user at the end.
447
446
deduplicated_warn_count: usize,
448
447
448
+ emitter: Box<DynEmitter>,
449
+
450
+ /// Must we produce a diagnostic to justify the use of the expensive
451
+ /// `trimmed_def_paths` function?
452
+ must_produce_diag: bool,
453
+
449
454
/// Has this diagnostic context printed any diagnostics? (I.e. has
450
455
/// `self.emitter.emit_diagnostic()` been called?
451
456
has_printed: bool,
452
457
453
- emitter: Box<DynEmitter>,
454
458
/// This flag indicates that an expected diagnostic was emitted and suppressed.
455
- /// This is used for the `good_path_delayed_bugs ` check.
459
+ /// This is used for the `must_produce_diag ` check.
456
460
suppressed_expected_diag: bool,
457
461
458
462
/// This set contains the code of all emitted diagnostics to avoid
@@ -533,11 +537,6 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
533
537
pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
534
538
AtomicRef::new(&(default_track_diagnostic as _));
535
539
536
- enum DelayedBugKind {
537
- Normal,
538
- GoodPath,
539
- }
540
-
541
540
#[derive(Copy, Clone, Default)]
542
541
pub struct DiagCtxtFlags {
543
542
/// If false, warning-level lints are suppressed.
@@ -563,11 +562,16 @@ impl Drop for DiagCtxtInner {
563
562
self.emit_stashed_diagnostics();
564
563
565
564
if self.err_guars.is_empty() {
566
- self.flush_delayed(DelayedBugKind::Normal )
565
+ self.flush_delayed()
567
566
}
568
567
569
568
if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
570
- self.flush_delayed(DelayedBugKind::GoodPath);
569
+ if self.must_produce_diag {
570
+ panic!(
571
+ "must_produce_diag: trimmed_def_paths called but no diagnostics emitted; \
572
+ use `DelayDm` for lints or `with_no_trimmed_paths` for debugging"
573
+ );
574
+ }
571
575
}
572
576
573
577
if self.check_unstable_expect_diagnostics {
@@ -609,12 +613,12 @@ impl DiagCtxt {
609
613
err_guars: Vec::new(),
610
614
lint_err_guars: Vec::new(),
611
615
delayed_bugs: Vec::new(),
612
- good_path_delayed_bugs: Vec::new(),
613
616
stashed_err_count: 0,
614
617
deduplicated_err_count: 0,
615
618
deduplicated_warn_count: 0,
616
- has_printed: false,
617
619
emitter,
620
+ must_produce_diag: false,
621
+ has_printed: false,
618
622
suppressed_expected_diag: false,
619
623
taught_diagnostics: Default::default(),
620
624
emitted_diagnostic_codes: Default::default(),
@@ -666,13 +670,14 @@ impl DiagCtxt {
666
670
inner.stashed_err_count = 0;
667
671
inner.deduplicated_err_count = 0;
668
672
inner.deduplicated_warn_count = 0;
673
+ inner.must_produce_diag = false;
669
674
inner.has_printed = false;
675
+ inner.suppressed_expected_diag = false;
670
676
671
677
// actually free the underlying memory (which `clear` would not do)
672
678
inner.err_guars = Default::default();
673
679
inner.lint_err_guars = Default::default();
674
680
inner.delayed_bugs = Default::default();
675
- inner.good_path_delayed_bugs = Default::default();
676
681
inner.taught_diagnostics = Default::default();
677
682
inner.emitted_diagnostic_codes = Default::default();
678
683
inner.emitted_diagnostics = Default::default();
@@ -934,7 +939,13 @@ impl DiagCtxt {
934
939
}
935
940
936
941
pub fn flush_delayed(&self) {
937
- self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
942
+ self.inner.borrow_mut().flush_delayed();
943
+ }
944
+
945
+ /// Used when trimmed_def_paths is called and we must produce a diagnostic
946
+ /// to justify its cost.
947
+ pub fn set_must_produce_diag(&self) {
948
+ self.inner.borrow_mut().must_produce_diag = true;
938
949
}
939
950
}
940
951
@@ -1108,13 +1119,6 @@ impl DiagCtxt {
1108
1119
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
1109
1120
}
1110
1121
1111
- /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`.
1112
- // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
1113
- #[track_caller]
1114
- pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
1115
- DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit()
1116
- }
1117
-
1118
1122
#[rustc_lint_diagnostics]
1119
1123
#[track_caller]
1120
1124
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
@@ -1266,19 +1270,17 @@ impl DiagCtxtInner {
1266
1270
if diagnostic.has_future_breakage() {
1267
1271
// Future breakages aren't emitted if they're Level::Allow,
1268
1272
// but they still need to be constructed and stashed below,
1269
- // so they'll trigger the good-path bug check.
1273
+ // so they'll trigger the must_produce_diag check.
1270
1274
self.suppressed_expected_diag = true;
1271
1275
self.future_breakage_diagnostics.push(diagnostic.clone());
1272
1276
}
1273
1277
1274
- if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug)
1275
- && self.flags.eagerly_emit_delayed_bugs
1276
- {
1278
+ if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
1277
1279
diagnostic.level = Error;
1278
1280
}
1279
1281
1280
1282
match diagnostic.level {
1281
- // This must come after the possible promotion of `DelayedBug`/`GoodPathDelayedBug` to
1283
+ // This must come after the possible promotion of `DelayedBug` to
1282
1284
// `Error` above.
1283
1285
Fatal | Error if self.treat_next_err_as_bug() => {
1284
1286
diagnostic.level = Bug;
@@ -1297,12 +1299,6 @@ impl DiagCtxtInner {
1297
1299
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
1298
1300
return Some(guar);
1299
1301
}
1300
- GoodPathDelayedBug => {
1301
- let backtrace = std::backtrace::Backtrace::capture();
1302
- self.good_path_delayed_bugs
1303
- .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
1304
- return None;
1305
- }
1306
1302
Warning if !self.flags.can_emit_warnings => {
1307
1303
if diagnostic.has_future_breakage() {
1308
1304
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
@@ -1414,23 +1410,14 @@ impl DiagCtxtInner {
1414
1410
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
1415
1411
}
1416
1412
1417
- fn flush_delayed(&mut self, kind: DelayedBugKind) {
1418
- let (bugs, note1) = match kind {
1419
- DelayedBugKind::Normal => (
1420
- std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(),
1421
- "no errors encountered even though delayed bugs were created",
1422
- ),
1423
- DelayedBugKind::GoodPath => (
1424
- std::mem::take(&mut self.good_path_delayed_bugs),
1425
- "no warnings or errors encountered even though good path delayed bugs were created",
1426
- ),
1427
- };
1428
- let note2 = "those delayed bugs will now be shown as internal compiler errors";
1429
-
1430
- if bugs.is_empty() {
1413
+ fn flush_delayed(&mut self) {
1414
+ if self.delayed_bugs.is_empty() {
1431
1415
return;
1432
1416
}
1433
1417
1418
+ let bugs: Vec<_> =
1419
+ std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1420
+
1434
1421
// If backtraces are enabled, also print the query stack
1435
1422
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
1436
1423
for (i, bug) in bugs.into_iter().enumerate() {
@@ -1454,6 +1441,8 @@ impl DiagCtxtInner {
1454
1441
// frame them better (e.g. separate warnings from them). Also,
1455
1442
// make it a note so it doesn't count as an error, because that
1456
1443
// could trigger `-Ztreat-err-as-bug`, which we don't want.
1444
+ let note1 = "no errors encountered even though delayed bugs were created";
1445
+ let note2 = "those delayed bugs will now be shown as internal compiler errors";
1457
1446
self.emit_diagnostic(Diagnostic::new(Note, note1));
1458
1447
self.emit_diagnostic(Diagnostic::new(Note, note2));
1459
1448
}
@@ -1462,7 +1451,7 @@ impl DiagCtxtInner {
1462
1451
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
1463
1452
1464
1453
// "Undelay" the delayed bugs (into plain `Bug`s).
1465
- if !matches!( bug.level, DelayedBug | GoodPathDelayedBug) {
1454
+ if bug.level != DelayedBug {
1466
1455
// NOTE(eddyb) not panicking here because we're already producing
1467
1456
// an ICE, and the more information the merrier.
1468
1457
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@@ -1534,7 +1523,6 @@ impl DelayedDiagnostic {
1534
1523
/// Fatal yes FatalAbort/FatalError(*) yes - -
1535
1524
/// Error yes ErrorGuaranteed yes - yes
1536
1525
/// DelayedBug yes ErrorGuaranteed yes - -
1537
- /// GoodPathDelayedBug - () yes - -
1538
1526
/// ForceWarning - () yes - lint-only
1539
1527
/// Warning - () yes yes yes
1540
1528
/// Note - () rare yes -
@@ -1567,20 +1555,6 @@ pub enum Level {
1567
1555
/// that should only be reached when compiling erroneous code.
1568
1556
DelayedBug,
1569
1557
1570
- /// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If
1571
- /// compilation ends without any other diagnostics being emitted (and without an expected lint
1572
- /// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped.
1573
- /// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths
1574
- /// that should only be reached when emitting diagnostics, e.g. for expensive one-time
1575
- /// diagnostic formatting operations.
1576
- ///
1577
- /// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce
1578
- /// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted.
1579
- /// Plus there's the extra complication with expected (suppressed) lints. They have limited
1580
- /// use, and are used in very few places, and "good path" isn't a good name. It would be good
1581
- /// to remove them.
1582
- GoodPathDelayedBug,
1583
-
1584
1558
/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation
1585
1559
/// from finishing.
1586
1560
///
@@ -1625,7 +1599,7 @@ impl Level {
1625
1599
fn color(self) -> ColorSpec {
1626
1600
let mut spec = ColorSpec::new();
1627
1601
match self {
1628
- Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => {
1602
+ Bug | Fatal | Error | DelayedBug => {
1629
1603
spec.set_fg(Some(Color::Red)).set_intense(true);
1630
1604
}
1631
1605
ForceWarning(_) | Warning => {
@@ -1645,7 +1619,7 @@ impl Level {
1645
1619
1646
1620
pub fn to_str(self) -> &'static str {
1647
1621
match self {
1648
- Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error",
1622
+ Bug | DelayedBug => "error: internal compiler error",
1649
1623
Fatal | Error => "error",
1650
1624
ForceWarning(_) | Warning => "warning",
1651
1625
Note | OnceNote => "note",
@@ -1670,8 +1644,8 @@ impl Level {
1670
1644
// subdiagnostic message?
1671
1645
fn can_be_top_or_sub(&self) -> (bool, bool) {
1672
1646
match self {
1673
- Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_)
1674
- | FailureNote | Allow | Expect(_) => (true, false),
1647
+ Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow
1648
+ | Expect(_) => (true, false),
1675
1649
1676
1650
Warning | Note | Help => (true, true),
1677
1651
0 commit comments