Skip to content

Commit f662cd8

Browse files
committed
Remove good_path_delayed_bug.
It's only has a single remaining purpose: to ensure that a diagnostic is printed when `trimmed_def_paths` is used. It's an annoying mechanism: weak, with odd semantics, badly named, and gets in the way of other changes. This commit replaces it with a simpler `must_produce_diag` mechanism, getting rid of a diagnostic `Level` along the way.
1 parent 7c7fcd8 commit f662cd8

File tree

9 files changed

+47
-111
lines changed

9 files changed

+47
-111
lines changed

compiler/rustc_const_eval/src/interpret/eval_context.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
288288
if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
289289
write!(f, "inside closure")
290290
} else {
291-
// Note: this triggers a `good_path_delayed_bug` state, which means that if we ever
291+
// Note: this triggers a `must_produce_diag` state, which means that if we ever
292292
// get here we must emit a diagnostic. We should never display a `FrameInfo` unless
293293
// we actually want to emit a warning or error to the user.
294294
write!(f, "inside `{}`", self.instance)
@@ -304,7 +304,7 @@ impl<'tcx> FrameInfo<'tcx> {
304304
errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
305305
} else {
306306
let instance = format!("{}", self.instance);
307-
// Note: this triggers a `good_path_delayed_bug` state, which means that if we ever get
307+
// Note: this triggers a `must_produce_diag` state, which means that if we ever get
308308
// here we must emit a diagnostic. We should never display a `FrameInfo` unless we
309309
// actually want to emit a warning or error to the user.
310310
errors::FrameNote { where_: "instance", span, instance, times: 0 }

compiler/rustc_error_messages/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ impl From<Cow<'static, str>> for DiagnosticMessage {
376376
}
377377
}
378378

379-
/// A workaround for good_path_delayed_bug ICEs when formatting types in disabled lints.
379+
/// A workaround for must_produce_diag ICEs when formatting types in disabled lints.
380380
///
381381
/// Delays formatting until `.into(): DiagnosticMessage` is used.
382382
pub struct DelayDm<F>(pub F);

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
8585
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
8686
fn annotation_type_for_level(level: Level) -> AnnotationType {
8787
match level {
88-
Level::Bug
89-
| Level::Fatal
90-
| Level::Error
91-
| Level::DelayedBug
92-
| Level::GoodPathDelayedBug => AnnotationType::Error,
88+
Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => AnnotationType::Error,
9389
Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
9490
Level::Note | Level::OnceNote => AnnotationType::Note,
9591
Level::Help | Level::OnceHelp => AnnotationType::Help,

compiler/rustc_errors/src/diagnostic.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ impl Diagnostic {
237237
match self.level {
238238
Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true,
239239

240-
Level::GoodPathDelayedBug
241-
| Level::ForceWarning(_)
240+
Level::ForceWarning(_)
242241
| Level::Warning
243242
| Level::Note
244243
| Level::OnceNote

compiler/rustc_errors/src/lib.rs

+31-58
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,13 @@ struct DiagCtxtInner {
448448

449449
emitter: Box<DynEmitter>,
450450
delayed_bugs: Vec<DelayedDiagnostic>,
451-
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
451+
452+
/// Must we produce a diagnostic to justify the use of the expensive
453+
/// `trimmed_def_paths` function?
454+
must_produce_diag: bool,
455+
452456
/// This flag indicates that an expected diagnostic was emitted and suppressed.
453-
/// This is used for the `good_path_delayed_bugs` check.
457+
/// This is used for the `must_produce_diag` check.
454458
suppressed_expected_diag: bool,
455459

456460
/// This set contains the code of all emitted diagnostics to avoid
@@ -531,11 +535,6 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
531535
pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
532536
AtomicRef::new(&(default_track_diagnostic as _));
533537

534-
enum DelayedBugKind {
535-
Normal,
536-
GoodPath,
537-
}
538-
539538
#[derive(Copy, Clone, Default)]
540539
pub struct DiagCtxtFlags {
541540
/// If false, warning-level lints are suppressed.
@@ -561,11 +560,16 @@ impl Drop for DiagCtxtInner {
561560
self.emit_stashed_diagnostics();
562561

563562
if !self.has_errors() {
564-
self.flush_delayed(DelayedBugKind::Normal)
563+
self.flush_delayed()
565564
}
566565

567566
if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
568-
self.flush_delayed(DelayedBugKind::GoodPath);
567+
if self.must_produce_diag {
568+
panic!(
569+
"must_produce_diag: trimmed_def_paths called but no diagnostics emitted; \
570+
use `DelayDm` for lints or `with_no_trimmed_paths` for debugging"
571+
);
572+
}
569573
}
570574

571575
if self.check_unstable_expect_diagnostics {
@@ -612,7 +616,7 @@ impl DiagCtxt {
612616
has_printed: false,
613617
emitter,
614618
delayed_bugs: Vec::new(),
615-
good_path_delayed_bugs: Vec::new(),
619+
must_produce_diag: false,
616620
suppressed_expected_diag: false,
617621
taught_diagnostics: Default::default(),
618622
emitted_diagnostic_codes: Default::default(),
@@ -670,7 +674,7 @@ impl DiagCtxt {
670674

671675
// actually free the underlying memory (which `clear` would not do)
672676
inner.delayed_bugs = Default::default();
673-
inner.good_path_delayed_bugs = Default::default();
677+
inner.must_produce_diag = false;
674678
inner.taught_diagnostics = Default::default();
675679
inner.emitted_diagnostic_codes = Default::default();
676680
inner.emitted_diagnostics = Default::default();
@@ -883,9 +887,10 @@ impl DiagCtxt {
883887
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
884888
}
885889

886-
/// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`.
887-
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
888-
DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit()
890+
/// Used when trimmed_def_paths is called and we must produce a diagnostic
891+
/// to justify its cost.
892+
pub fn set_must_produce_diag(&self) {
893+
self.inner.borrow_mut().must_produce_diag = true;
889894
}
890895

891896
#[track_caller]
@@ -1225,7 +1230,7 @@ impl DiagCtxt {
12251230
}
12261231

12271232
pub fn flush_delayed(&self) {
1228-
self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
1233+
self.inner.borrow_mut().flush_delayed();
12291234
}
12301235
}
12311236

@@ -1275,14 +1280,12 @@ impl DiagCtxtInner {
12751280
if diagnostic.has_future_breakage() {
12761281
// Future breakages aren't emitted if they're Level::Allow,
12771282
// but they still need to be constructed and stashed below,
1278-
// so they'll trigger the good-path bug check.
1283+
// so they'll trigger the must_produce_diag check.
12791284
self.suppressed_expected_diag = true;
12801285
self.future_breakage_diagnostics.push(diagnostic.clone());
12811286
}
12821287

1283-
if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug)
1284-
&& self.flags.eagerly_emit_delayed_bugs
1285-
{
1288+
if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
12861289
diagnostic.level = Error;
12871290
}
12881291

@@ -1302,12 +1305,6 @@ impl DiagCtxtInner {
13021305
#[allow(deprecated)]
13031306
return Some(ErrorGuaranteed::unchecked_error_guaranteed());
13041307
}
1305-
GoodPathDelayedBug => {
1306-
let backtrace = std::backtrace::Backtrace::capture();
1307-
self.good_path_delayed_bugs
1308-
.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
1309-
return None;
1310-
}
13111308
Warning if !self.flags.can_emit_warnings => {
13121309
if diagnostic.has_future_breakage() {
13131310
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
@@ -1409,19 +1406,8 @@ impl DiagCtxtInner {
14091406
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
14101407
}
14111408

1412-
fn flush_delayed(&mut self, kind: DelayedBugKind) {
1413-
let (bugs, note1) = match kind {
1414-
DelayedBugKind::Normal => (
1415-
std::mem::take(&mut self.delayed_bugs),
1416-
"no errors encountered even though delayed bugs were created",
1417-
),
1418-
DelayedBugKind::GoodPath => (
1419-
std::mem::take(&mut self.good_path_delayed_bugs),
1420-
"no warnings or errors encountered even though good path delayed bugs were created",
1421-
),
1422-
};
1423-
let note2 = "those delayed bugs will now be shown as internal compiler errors";
1424-
1409+
fn flush_delayed(&mut self) {
1410+
let bugs = std::mem::take(&mut self.delayed_bugs);
14251411
if bugs.is_empty() {
14261412
return;
14271413
}
@@ -1449,6 +1435,8 @@ impl DiagCtxtInner {
14491435
// frame them better (e.g. separate warnings from them). Also,
14501436
// make it a note so it doesn't count as an error, because that
14511437
// could trigger `-Ztreat-err-as-bug`, which we don't want.
1438+
let note1 = "no errors encountered even though delayed bugs were created";
1439+
let note2 = "those delayed bugs will now be shown as internal compiler errors";
14521440
self.emit_diagnostic(Diagnostic::new(Note, note1));
14531441
self.emit_diagnostic(Diagnostic::new(Note, note2));
14541442
}
@@ -1457,7 +1445,7 @@ impl DiagCtxtInner {
14571445
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
14581446

14591447
// "Undelay" the delayed bugs (into plain `Bug`s).
1460-
if !matches!(bug.level, DelayedBug | GoodPathDelayedBug) {
1448+
if bug.level != DelayedBug {
14611449
// NOTE(eddyb) not panicking here because we're already producing
14621450
// an ICE, and the more information the merrier.
14631451
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@@ -1529,7 +1517,6 @@ impl DelayedDiagnostic {
15291517
/// Fatal yes FatalAbort/FatalError(*) yes - -
15301518
/// Error yes ErrorGuaranteed yes - yes
15311519
/// DelayedBug yes ErrorGuaranteed yes - -
1532-
/// GoodPathDelayedBug - () yes - -
15331520
/// ForceWarning - () yes - lint-only
15341521
/// Warning - () yes yes yes
15351522
/// Note - () rare yes -
@@ -1562,20 +1549,6 @@ pub enum Level {
15621549
/// that should only be reached when compiling erroneous code.
15631550
DelayedBug,
15641551

1565-
/// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If
1566-
/// compilation ends without any other diagnostics being emitted (and without an expected lint
1567-
/// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped.
1568-
/// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths
1569-
/// that should only be reached when emitting diagnostics, e.g. for expensive one-time
1570-
/// diagnostic formatting operations.
1571-
///
1572-
/// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce
1573-
/// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted.
1574-
/// Plus there's the extra complication with expected (suppressed) lints. They have limited
1575-
/// use, and are used in very few places, and "good path" isn't a good name. It would be good
1576-
/// to remove them.
1577-
GoodPathDelayedBug,
1578-
15791552
/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation
15801553
/// from finishing.
15811554
///
@@ -1619,7 +1592,7 @@ impl Level {
16191592
fn color(self) -> ColorSpec {
16201593
let mut spec = ColorSpec::new();
16211594
match self {
1622-
Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => {
1595+
Bug | Fatal | Error | DelayedBug => {
16231596
spec.set_fg(Some(Color::Red)).set_intense(true);
16241597
}
16251598
ForceWarning(_) | Warning => {
@@ -1639,7 +1612,7 @@ impl Level {
16391612

16401613
pub fn to_str(self) -> &'static str {
16411614
match self {
1642-
Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error",
1615+
Bug | DelayedBug => "error: internal compiler error",
16431616
Fatal | Error => "error",
16441617
ForceWarning(_) | Warning => "warning",
16451618
Note | OnceNote => "note",
@@ -1664,8 +1637,8 @@ impl Level {
16641637
// subdiagnostic message?
16651638
fn can_be_top_or_sub(&self) -> (bool, bool) {
16661639
match self {
1667-
Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_)
1668-
| FailureNote | Allow | Expect(_) => (true, false),
1640+
Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow
1641+
| Expect(_) => (true, false),
16691642

16701643
Warning | Note | Help => (true, true),
16711644

compiler/rustc_middle/src/ty/print/pretty.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -3156,13 +3156,12 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
31563156
// this is pub to be able to intra-doc-link it
31573157
pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
31583158
// Trimming paths is expensive and not optimized, since we expect it to only be used for error
3159-
// reporting.
3159+
// reporting. Record the fact that we did it, so we can abort if we later found it was
3160+
// unnecessary.
31603161
//
3161-
// For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
3162-
// wrapper can be used to suppress this query, in exchange for full paths being formatted.
3163-
tcx.sess.good_path_delayed_bug(
3164-
"trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
3165-
);
3162+
// The `rustc_middle::ty::print::with_no_trimmed_paths` wrapper can be used to suppress this
3163+
// checking, in exchange for full paths being formatted.
3164+
tcx.sess.record_trimmed_def_paths();
31663165

31673166
// Once constructed, unique namespace+symbol pairs will have a `Some(_)` entry, while
31683167
// non-unique pairs will have a `None` entry.

compiler/rustc_session/src/session.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,9 @@ impl Session {
322322
}
323323
}
324324

325-
/// Used for code paths of expensive computations that should only take place when
326-
/// warnings or errors are emitted. If no messages are emitted ("good path"), then
327-
/// it's likely a bug.
328-
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
325+
/// Record the fact that we called `trimmed_def_paths`, and do some
326+
/// checking about whether its cost was justified.
327+
pub fn record_trimmed_def_paths(&self) {
329328
if self.opts.unstable_opts.print_type_sizes
330329
|| self.opts.unstable_opts.query_dep_graph
331330
|| self.opts.unstable_opts.dump_mir.is_some()
@@ -336,7 +335,7 @@ impl Session {
336335
return;
337336
}
338337

339-
self.dcx().good_path_delayed_bug(msg)
338+
self.dcx().set_must_produce_diag()
340339
}
341340

342341
#[inline]
@@ -546,8 +545,8 @@ impl Session {
546545
if fuel.remaining == 0 && !fuel.out_of_fuel {
547546
if self.dcx().can_emit_warnings() {
548547
// We only call `msg` in case we can actually emit warnings.
549-
// Otherwise, this could cause a `good_path_delayed_bug` to
550-
// trigger (issue #79546).
548+
// Otherwise, this could cause a `must_produce_diag` ICE
549+
// (issue #79546).
551550
self.dcx().emit_warn(errors::OptimisationFuelExhausted { msg: msg() });
552551
}
553552
fuel.out_of_fuel = true;

tests/ui/treat-err-as-bug/eagerly-emit.rs

-10
This file was deleted.

tests/ui/treat-err-as-bug/eagerly-emit.stderr

-20
This file was deleted.

0 commit comments

Comments
 (0)