Skip to content

Commit 767518a

Browse files
authored
Rollup merge of rust-lang#120959 - nnethercote:rm-good_path, r=oli-obk
Remove good path delayed bugs Because they're not that useful, and kind of annoying. Details in the individual commits. r? `@compiler-errors`
2 parents 4bbe53b + 9f2aa09 commit 767518a

File tree

10 files changed

+56
-133
lines changed

10 files changed

+56
-133
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

+40-66
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,6 @@ struct DiagCtxtInner {
436436
lint_err_guars: Vec<ErrorGuaranteed>,
437437
/// The delayed bugs and their error guarantees.
438438
delayed_bugs: Vec<(DelayedDiagnostic, ErrorGuaranteed)>,
439-
good_path_delayed_bugs: Vec<DelayedDiagnostic>,
440439

441440
/// The number of stashed errors. Unlike the other counts, this can go up
442441
/// and down, so it doesn't guarantee anything.
@@ -447,13 +446,18 @@ struct DiagCtxtInner {
447446
/// The warning count shown to the user at the end.
448447
deduplicated_warn_count: usize,
449448

449+
emitter: Box<DynEmitter>,
450+
451+
/// Must we produce a diagnostic to justify the use of the expensive
452+
/// `trimmed_def_paths` function?
453+
must_produce_diag: bool,
454+
450455
/// Has this diagnostic context printed any diagnostics? (I.e. has
451456
/// `self.emitter.emit_diagnostic()` been called?
452457
has_printed: bool,
453458

454-
emitter: Box<DynEmitter>,
455459
/// This flag indicates that an expected diagnostic was emitted and suppressed.
456-
/// This is used for the `good_path_delayed_bugs` check.
460+
/// This is used for the `must_produce_diag` check.
457461
suppressed_expected_diag: bool,
458462

459463
/// This set contains the code of all emitted diagnostics to avoid
@@ -534,11 +538,6 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
534538
pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
535539
AtomicRef::new(&(default_track_diagnostic as _));
536540

537-
enum DelayedBugKind {
538-
Normal,
539-
GoodPath,
540-
}
541-
542541
#[derive(Copy, Clone, Default)]
543542
pub struct DiagCtxtFlags {
544543
/// If false, warning-level lints are suppressed.
@@ -564,11 +563,16 @@ impl Drop for DiagCtxtInner {
564563
self.emit_stashed_diagnostics();
565564

566565
if self.err_guars.is_empty() {
567-
self.flush_delayed(DelayedBugKind::Normal)
566+
self.flush_delayed()
568567
}
569568

570569
if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
571-
self.flush_delayed(DelayedBugKind::GoodPath);
570+
if self.must_produce_diag {
571+
panic!(
572+
"must_produce_diag: trimmed_def_paths called but no diagnostics emitted; \
573+
use `DelayDm` for lints or `with_no_trimmed_paths` for debugging"
574+
);
575+
}
572576
}
573577

574578
if self.check_unstable_expect_diagnostics {
@@ -610,12 +614,12 @@ impl DiagCtxt {
610614
err_guars: Vec::new(),
611615
lint_err_guars: Vec::new(),
612616
delayed_bugs: Vec::new(),
613-
good_path_delayed_bugs: Vec::new(),
614617
stashed_err_count: 0,
615618
deduplicated_err_count: 0,
616619
deduplicated_warn_count: 0,
617-
has_printed: false,
618620
emitter,
621+
must_produce_diag: false,
622+
has_printed: false,
619623
suppressed_expected_diag: false,
620624
taught_diagnostics: Default::default(),
621625
emitted_diagnostic_codes: Default::default(),
@@ -667,13 +671,14 @@ impl DiagCtxt {
667671
inner.stashed_err_count = 0;
668672
inner.deduplicated_err_count = 0;
669673
inner.deduplicated_warn_count = 0;
674+
inner.must_produce_diag = false;
670675
inner.has_printed = false;
676+
inner.suppressed_expected_diag = false;
671677

672678
// actually free the underlying memory (which `clear` would not do)
673679
inner.err_guars = Default::default();
674680
inner.lint_err_guars = Default::default();
675681
inner.delayed_bugs = Default::default();
676-
inner.good_path_delayed_bugs = Default::default();
677682
inner.taught_diagnostics = Default::default();
678683
inner.emitted_diagnostic_codes = Default::default();
679684
inner.emitted_diagnostics = Default::default();
@@ -935,7 +940,13 @@ impl DiagCtxt {
935940
}
936941

937942
pub fn flush_delayed(&self) {
938-
self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
943+
self.inner.borrow_mut().flush_delayed();
944+
}
945+
946+
/// Used when trimmed_def_paths is called and we must produce a diagnostic
947+
/// to justify its cost.
948+
pub fn set_must_produce_diag(&self) {
949+
self.inner.borrow_mut().must_produce_diag = true;
939950
}
940951
}
941952

@@ -1109,13 +1120,6 @@ impl DiagCtxt {
11091120
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
11101121
}
11111122

1112-
/// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`.
1113-
// No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
1114-
#[track_caller]
1115-
pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
1116-
DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit()
1117-
}
1118-
11191123
#[rustc_lint_diagnostics]
11201124
#[track_caller]
11211125
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
@@ -1267,19 +1271,17 @@ impl DiagCtxtInner {
12671271
if diagnostic.has_future_breakage() {
12681272
// Future breakages aren't emitted if they're Level::Allow,
12691273
// but they still need to be constructed and stashed below,
1270-
// so they'll trigger the good-path bug check.
1274+
// so they'll trigger the must_produce_diag check.
12711275
self.suppressed_expected_diag = true;
12721276
self.future_breakage_diagnostics.push(diagnostic.clone());
12731277
}
12741278

1275-
if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug)
1276-
&& self.flags.eagerly_emit_delayed_bugs
1277-
{
1279+
if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
12781280
diagnostic.level = Error;
12791281
}
12801282

12811283
match diagnostic.level {
1282-
// This must come after the possible promotion of `DelayedBug`/`GoodPathDelayedBug` to
1284+
// This must come after the possible promotion of `DelayedBug` to
12831285
// `Error` above.
12841286
Fatal | Error if self.treat_next_err_as_bug() => {
12851287
diagnostic.level = Bug;
@@ -1298,12 +1300,6 @@ impl DiagCtxtInner {
12981300
.push((DelayedDiagnostic::with_backtrace(diagnostic, backtrace), guar));
12991301
return Some(guar);
13001302
}
1301-
GoodPathDelayedBug => {
1302-
let backtrace = std::backtrace::Backtrace::capture();
1303-
self.good_path_delayed_bugs
1304-
.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
1305-
return None;
1306-
}
13071303
Warning if !self.flags.can_emit_warnings => {
13081304
if diagnostic.has_future_breakage() {
13091305
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
@@ -1415,23 +1411,14 @@ impl DiagCtxtInner {
14151411
self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
14161412
}
14171413

1418-
fn flush_delayed(&mut self, kind: DelayedBugKind) {
1419-
let (bugs, note1) = match kind {
1420-
DelayedBugKind::Normal => (
1421-
std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(),
1422-
"no errors encountered even though delayed bugs were created",
1423-
),
1424-
DelayedBugKind::GoodPath => (
1425-
std::mem::take(&mut self.good_path_delayed_bugs),
1426-
"no warnings or errors encountered even though good path delayed bugs were created",
1427-
),
1428-
};
1429-
let note2 = "those delayed bugs will now be shown as internal compiler errors";
1430-
1431-
if bugs.is_empty() {
1414+
fn flush_delayed(&mut self) {
1415+
if self.delayed_bugs.is_empty() {
14321416
return;
14331417
}
14341418

1419+
let bugs: Vec<_> =
1420+
std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
1421+
14351422
// If backtraces are enabled, also print the query stack
14361423
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
14371424
for (i, bug) in bugs.into_iter().enumerate() {
@@ -1455,6 +1442,8 @@ impl DiagCtxtInner {
14551442
// frame them better (e.g. separate warnings from them). Also,
14561443
// make it a note so it doesn't count as an error, because that
14571444
// could trigger `-Ztreat-err-as-bug`, which we don't want.
1445+
let note1 = "no errors encountered even though delayed bugs were created";
1446+
let note2 = "those delayed bugs will now be shown as internal compiler errors";
14581447
self.emit_diagnostic(Diagnostic::new(Note, note1));
14591448
self.emit_diagnostic(Diagnostic::new(Note, note2));
14601449
}
@@ -1463,7 +1452,7 @@ impl DiagCtxtInner {
14631452
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
14641453

14651454
// "Undelay" the delayed bugs (into plain `Bug`s).
1466-
if !matches!(bug.level, DelayedBug | GoodPathDelayedBug) {
1455+
if bug.level != DelayedBug {
14671456
// NOTE(eddyb) not panicking here because we're already producing
14681457
// an ICE, and the more information the merrier.
14691458
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@@ -1535,7 +1524,6 @@ impl DelayedDiagnostic {
15351524
/// Fatal yes FatalAbort/FatalError(*) yes - -
15361525
/// Error yes ErrorGuaranteed yes - yes
15371526
/// DelayedBug yes ErrorGuaranteed yes - -
1538-
/// GoodPathDelayedBug - () yes - -
15391527
/// ForceWarning - () yes - lint-only
15401528
/// Warning - () yes yes yes
15411529
/// Note - () rare yes -
@@ -1568,20 +1556,6 @@ pub enum Level {
15681556
/// that should only be reached when compiling erroneous code.
15691557
DelayedBug,
15701558

1571-
/// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If
1572-
/// compilation ends without any other diagnostics being emitted (and without an expected lint
1573-
/// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped.
1574-
/// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths
1575-
/// that should only be reached when emitting diagnostics, e.g. for expensive one-time
1576-
/// diagnostic formatting operations.
1577-
///
1578-
/// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce
1579-
/// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted.
1580-
/// Plus there's the extra complication with expected (suppressed) lints. They have limited
1581-
/// use, and are used in very few places, and "good path" isn't a good name. It would be good
1582-
/// to remove them.
1583-
GoodPathDelayedBug,
1584-
15851559
/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation
15861560
/// from finishing.
15871561
///
@@ -1626,7 +1600,7 @@ impl Level {
16261600
fn color(self) -> ColorSpec {
16271601
let mut spec = ColorSpec::new();
16281602
match self {
1629-
Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => {
1603+
Bug | Fatal | Error | DelayedBug => {
16301604
spec.set_fg(Some(Color::Red)).set_intense(true);
16311605
}
16321606
ForceWarning(_) | Warning => {
@@ -1646,7 +1620,7 @@ impl Level {
16461620

16471621
pub fn to_str(self) -> &'static str {
16481622
match self {
1649-
Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error",
1623+
Bug | DelayedBug => "error: internal compiler error",
16501624
Fatal | Error => "error",
16511625
ForceWarning(_) | Warning => "warning",
16521626
Note | OnceNote => "note",
@@ -1671,8 +1645,8 @@ impl Level {
16711645
// subdiagnostic message?
16721646
fn can_be_top_or_sub(&self) -> (bool, bool) {
16731647
match self {
1674-
Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_)
1675-
| FailureNote | Allow | Expect(_) => (true, false),
1648+
Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow
1649+
| Expect(_) => (true, false),
16761650

16771651
Warning | Note | Help => (true, true),
16781652

compiler/rustc_infer/src/infer/error_reporting/mod.rs

-14
Original file line numberDiff line numberDiff line change
@@ -132,20 +132,6 @@ pub struct TypeErrCtxt<'a, 'tcx> {
132132
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
133133
}
134134

135-
impl Drop for TypeErrCtxt<'_, '_> {
136-
fn drop(&mut self) {
137-
if self.dcx().has_errors().is_some() {
138-
// Ok, emitted an error.
139-
} else {
140-
// Didn't emit an error; maybe it was created but not yet emitted.
141-
self.infcx
142-
.tcx
143-
.sess
144-
.good_path_delayed_bug("used a `TypeErrCtxt` without raising an error or lint");
145-
}
146-
}
147-
}
148-
149135
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
150136
pub fn dcx(&self) -> &'tcx DiagCtxt {
151137
self.infcx.tcx.dcx()

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.

0 commit comments

Comments
 (0)