Skip to content

Commit 36f93cb

Browse files
committed
Split delayed bugs into has-errored and will-error halves.
This commit adds new `{span_,}assert_has_errors` methods implementing the simpler has-errored cases, and leaves the existing `{span_,}delayed_bug` methods for the will-error cases. It also converts as many cases as possible to has-errored. I did this by converting every case to has-errored, then running tests and converting back to will-error every case that caused an assertion in the test suite. The test suite doesn't have perfect coverage so it's possible that there are a few more has-errored cases that will need conversion back to will-error. Also, some of the will-error cases might actually be a mixture of has-errored and will-error. But it's hard to do this perfectly without carefully going through every individual case, which would be painful, and an imperfect split still gets most of the benefits.
1 parent f484cf9 commit 36f93cb

File tree

92 files changed

+266
-200
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+266
-200
lines changed

Diff for: compiler/rustc_abi/src/layout.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ where
3232
pub trait LayoutCalculator {
3333
type TargetDataLayoutRef: Borrow<TargetDataLayout>;
3434

35-
fn delayed_bug(&self, txt: String);
35+
fn assert_has_errors(&self, txt: String);
3636
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
3737

3838
fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
@@ -259,7 +259,7 @@ pub trait LayoutCalculator {
259259
let only_variant = &variants[VariantIdx::new(0)];
260260
for field in only_variant {
261261
if field.is_unsized() {
262-
self.delayed_bug("unsized field in union".to_string());
262+
self.assert_has_errors("unsized field in union".to_string());
263263
}
264264

265265
align = align.max(field.align);
@@ -1092,7 +1092,7 @@ fn univariant<
10921092
for &i in &inverse_memory_index {
10931093
let field = &fields[i];
10941094
if !sized {
1095-
this.delayed_bug(format!(
1095+
this.assert_has_errors(format!(
10961096
"univariant: field #{} comes after unsized field",
10971097
offsets.len(),
10981098
));

Diff for: compiler/rustc_ast_lowering/src/delegation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
112112
sig_id.ok_or_else(|| {
113113
self.tcx
114114
.dcx()
115-
.span_delayed_bug(span, "LoweringContext: couldn't resolve delegation item")
115+
.span_assert_has_errors(span, "LoweringContext: couldn't resolve delegation item")
116116
})
117117
}
118118

Diff for: compiler/rustc_ast_lowering/src/expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
323323
)
324324
}
325325
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
326-
ExprKind::Err => {
327-
hir::ExprKind::Err(self.dcx().span_delayed_bug(e.span, "lowered ExprKind::Err"))
328-
}
326+
ExprKind::Err => hir::ExprKind::Err(
327+
self.dcx().span_assert_has_errors(e.span, "lowered ExprKind::Err"),
328+
),
329329
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
330330

331331
ExprKind::Paren(_) | ExprKind::ForLoop { .. } => {

Diff for: compiler/rustc_ast_lowering/src/format.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ fn make_count<'hir>(
267267
ctx.expr(
268268
sp,
269269
hir::ExprKind::Err(
270-
ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count"),
270+
ctx.dcx().span_assert_has_errors(sp, "lowered bad format_args count"),
271271
),
272272
)
273273
}
@@ -306,7 +306,9 @@ fn make_format_spec<'hir>(
306306
}
307307
Err(_) => ctx.expr(
308308
sp,
309-
hir::ExprKind::Err(ctx.dcx().span_delayed_bug(sp, "lowered bad format_args count")),
309+
hir::ExprKind::Err(
310+
ctx.dcx().span_assert_has_errors(sp, "lowered bad format_args count"),
311+
),
310312
),
311313
};
312314
let &FormatOptions {

Diff for: compiler/rustc_ast_lowering/src/index.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub(super) fn index_hir<'hir>(
6161
if let Node::Err(span) = node.node {
6262
let hir_id = HirId { owner: item.def_id(), local_id };
6363
let msg = format!("ID {hir_id} not encountered when visiting item HIR");
64-
tcx.dcx().span_delayed_bug(*span, msg);
64+
tcx.dcx().span_assert_has_errors(*span, msg);
6565
}
6666
}
6767

Diff for: compiler/rustc_ast_lowering/src/item.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
266266
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
267267
|this| match ty {
268268
None => {
269-
let guar = this.dcx().span_delayed_bug(
269+
let guar = this.dcx().span_assert_has_errors(
270270
span,
271271
"expected to lower type alias type, but it was missing",
272272
);
@@ -925,7 +925,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
925925
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
926926
|this| match ty {
927927
None => {
928-
let guar = this.dcx().span_delayed_bug(
928+
let guar = this.dcx().span_assert_has_errors(
929929
i.span,
930930
"expected to lower associated type, but it was missing",
931931
);
@@ -1068,7 +1068,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10681068
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
10691069
match block {
10701070
Some(block) => self.lower_block_expr(block),
1071-
None => self.expr_err(span, self.dcx().span_delayed_bug(span, "no block")),
1071+
None => self.expr_err(span, self.dcx().span_assert_has_errors(span, "no block")),
10721072
}
10731073
}
10741074

@@ -1078,7 +1078,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
10781078
&[],
10791079
match expr {
10801080
Some(expr) => this.lower_expr_mut(expr),
1081-
None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
1081+
None => {
1082+
this.expr_err(span, this.dcx().span_assert_has_errors(span, "no block"))
1083+
}
10821084
},
10831085
)
10841086
})

Diff for: compiler/rustc_ast_lowering/src/lib.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
747747
let res = self.resolver.get_import_res(id).present_items();
748748
let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect();
749749
if res.is_empty() {
750-
self.dcx().span_delayed_bug(span, "no resolution for an import");
750+
self.dcx().span_assert_has_errors(span, "no resolution for an import");
751751
return smallvec![Res::Err];
752752
}
753753
res
@@ -1286,7 +1286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12861286
let kind = match &t.kind {
12871287
TyKind::Infer => hir::TyKind::Infer,
12881288
TyKind::Err => {
1289-
hir::TyKind::Err(self.dcx().span_delayed_bug(t.span, "TyKind::Err lowered"))
1289+
hir::TyKind::Err(self.dcx().span_assert_has_errors(t.span, "TyKind::Err lowered"))
12901290
}
12911291
// Lower the anonymous structs or unions in a nested lowering context.
12921292
//
@@ -1499,7 +1499,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14991499
}
15001500
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
15011501
TyKind::CVarArgs => {
1502-
let guar = self.dcx().span_delayed_bug(
1502+
let guar = self.dcx().span_assert_has_errors(
15031503
t.span,
15041504
"`TyKind::CVarArgs` should have been handled elsewhere",
15051505
);
@@ -1643,8 +1643,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16431643
if let Some(old_def_id) = self.orig_opt_local_def_id(param) {
16441644
old_def_id
16451645
} else {
1646-
self.dcx()
1647-
.span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime");
1646+
self.dcx().span_assert_has_errors(
1647+
lifetime.ident.span,
1648+
"no def-id for fresh lifetime",
1649+
);
16481650
continue;
16491651
}
16501652
}
@@ -2576,7 +2578,7 @@ impl<'hir> GenericArgsCtor<'hir> {
25762578
let span = lcx.lower_span(span);
25772579

25782580
let Some(host_param_id) = lcx.host_param_id else {
2579-
lcx.dcx().span_delayed_bug(
2581+
lcx.dcx().span_assert_has_errors(
25802582
span,
25812583
"no host param id for call in const yet no errors reported",
25822584
);

Diff for: compiler/rustc_borrowck/src/diagnostics/region_name.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -627,8 +627,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
627627
_,
628628
) => {
629629
// HIR lowering sometimes doesn't catch this in erroneous
630-
// programs, so we need to use span_delayed_bug here. See #82126.
631-
self.dcx().span_delayed_bug(
630+
// programs, so we need to use span_assert_has_errors here. See #82126.
631+
self.dcx().span_assert_has_errors(
632632
hir_arg.span(),
633633
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
634634
);

Diff for: compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
316316
.and(type_op::normalize::Normalize::new(ty))
317317
.fully_perform(self.infcx, span)
318318
else {
319-
tcx.dcx().span_delayed_bug(span, format!("failed to normalize {ty:?}"));
319+
tcx.dcx().span_assert_has_errors(span, format!("failed to normalize {ty:?}"));
320320
continue;
321321
};
322322
constraints.extend(c);

Diff for: compiler/rustc_borrowck/src/type_check/input_output.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
152152
// Equate expected input tys with those in the MIR.
153153
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
154154
if argument_index + 1 >= body.local_decls.len() {
155-
self.tcx()
156-
.dcx()
157-
.span_delayed_bug(body.span, "found more normalized_input_ty than local_decls");
155+
self.tcx().dcx().span_assert_has_errors(
156+
body.span,
157+
"found more normalized_input_ty than local_decls",
158+
);
158159
break;
159160
}
160161

Diff for: compiler/rustc_borrowck/src/type_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
223223
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
224224
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
225225
if hidden_type.has_non_region_infer() {
226-
let reported = infcx.dcx().span_delayed_bug(
226+
let reported = infcx.dcx().span_assert_has_errors(
227227
decl.hidden_type.span,
228228
format!("could not resolve {:#?}", hidden_type.ty.kind()),
229229
);
@@ -1089,7 +1089,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10891089
);
10901090

10911091
if result.is_err() {
1092-
self.infcx.dcx().span_delayed_bug(
1092+
self.infcx.dcx().span_assert_has_errors(
10931093
self.body.span,
10941094
"failed re-defining predefined opaques in mir typeck",
10951095
);

Diff for: compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
9090
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
9191
Some(tcx.fn_sig(did))
9292
} else {
93-
tcx.dcx()
94-
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
93+
tcx.dcx().span_assert_has_errors(
94+
attr.span,
95+
"this attribute can only be applied to functions",
96+
);
9597
None
9698
}
9799
};

Diff for: compiler/rustc_const_eval/src/const_eval/machine.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
388388
if ecx.tcx.is_ctfe_mir_available(def) {
389389
Ok(ecx.tcx.mir_for_ctfe(def))
390390
} else if ecx.tcx.def_kind(def) == DefKind::AssocConst {
391-
let guar = ecx
392-
.tcx
393-
.dcx()
394-
.delayed_bug("This is likely a const item that is missing from its impl");
391+
let guar = ecx.tcx.dcx().assert_has_errors(
392+
"This is likely a const item that is missing from its impl",
393+
);
395394
throw_inval!(AlreadyReported(guar.into()));
396395
} else {
397396
// `find_mir_or_eval_fn` checks that this is a const fn before even calling us,

Diff for: compiler/rustc_const_eval/src/transform/check_consts/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
217217
// `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
218218
// no need to emit duplicate errors here.
219219
if self.ccx.is_async() || body.coroutine.is_some() {
220-
tcx.dcx().span_delayed_bug(body.span, "`async` functions cannot be `const fn`");
220+
tcx.dcx().span_assert_has_errors(body.span, "`async` functions cannot be `const fn`");
221221
return;
222222
}
223223

@@ -331,7 +331,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
331331
if self.tcx.is_thread_local_static(def_id) {
332332
self.tcx
333333
.dcx()
334-
.span_delayed_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
334+
.span_assert_has_errors(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
335335
}
336336
self.check_op_spanned(ops::StaticAccess, span)
337337
}

Diff for: compiler/rustc_const_eval/src/transform/check_consts/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
117117
None if is_parent_const_stable_trait(tcx, def_id) => {
118118
// Remove this when `#![feature(const_trait_impl)]` is stabilized,
119119
// returning `true` unconditionally.
120-
tcx.dcx().span_delayed_bug(
120+
tcx.dcx().span_assert_has_errors(
121121
tcx.def_span(def_id),
122122
"trait implementations cannot be const stable yet",
123123
);

Diff for: compiler/rustc_const_eval/src/transform/validate.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
118118
#[track_caller]
119119
fn fail(&self, location: Location, msg: impl AsRef<str>) {
120120
let span = self.body.source_info(location).span;
121-
// We use `span_delayed_bug` as we might see broken MIR when other errors have already
121+
// We use `span_assert_has_errors` as we might see broken MIR when other errors have already
122122
// occurred.
123-
self.tcx.dcx().span_delayed_bug(
123+
self.tcx.dcx().span_assert_has_errors(
124124
span,
125125
format!(
126126
"broken MIR in {:?} ({}) at {:?}:\n{}",
@@ -501,7 +501,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
501501

502502
fn visit_source_scope(&mut self, scope: SourceScope) {
503503
if self.body.source_scopes.get(scope).is_none() {
504-
self.tcx.dcx().span_delayed_bug(
504+
self.tcx.dcx().span_assert_has_errors(
505505
self.body.span,
506506
format!(
507507
"broken MIR in {:?} ({}):\ninvalid source scope {:?}",

Diff for: compiler/rustc_errors/src/lib.rs

+28-3
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,28 @@ impl DiagCtxt {
947947
pub fn set_must_produce_diag(&self) {
948948
self.inner.borrow_mut().must_produce_diag = true;
949949
}
950+
951+
/// Asserts that an error has already been printed.
952+
pub fn assert_has_errors(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
953+
if let Some(guar) = self.has_errors() {
954+
guar
955+
} else {
956+
panic!("`assert_has_errors` failed: {:?}", msg.into());
957+
}
958+
}
959+
960+
/// Asserts that an error has already been printed.
961+
pub fn span_assert_has_errors(
962+
&self,
963+
sp: impl Into<MultiSpan>,
964+
msg: impl Into<DiagnosticMessage>,
965+
) -> ErrorGuaranteed {
966+
if let Some(guar) = self.has_errors() {
967+
guar
968+
} else {
969+
panic!("`span_assert_has_errors` failed: {:?}, {:?}", msg.into(), sp.into());
970+
}
971+
}
950972
}
951973

952974
// This `impl` block contains only the public diagnostic creation/emission API.
@@ -1098,14 +1120,14 @@ impl DiagCtxt {
10981120
self.create_err(err).emit()
10991121
}
11001122

1101-
/// Ensures that an error is printed. See `Level::DelayedBug`.
1123+
/// Ensures that an error will be emitted later. See `Level::DelayedBug`.
11021124
// No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
11031125
#[track_caller]
11041126
pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
11051127
DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit()
11061128
}
11071129

1108-
/// Ensures that an error is printed. See `Level::DelayedBug`.
1130+
/// Ensures that an error will be emitted later. See `Level::DelayedBug`.
11091131
///
11101132
/// Note: this function used to be called `delay_span_bug`. It was renamed
11111133
/// to match similar functions like `span_err`, `span_warn`, etc.
@@ -1566,8 +1588,11 @@ pub enum Level {
15661588

15671589
/// This is a strange one: lets you register an error without emitting it. If compilation ends
15681590
/// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be
1569-
/// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
1591+
/// silently dropped. I.e. "expect more errors will be emitted" semantics. Useful on code paths
15701592
/// that should only be reached when compiling erroneous code.
1593+
///
1594+
/// Note: if you want "expect errors have already been emitted" semantics, use the simpler
1595+
/// `DiagCtxt::assert_has_errors` method.
15711596
DelayedBug,
15721597

15731598
/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation

Diff for: compiler/rustc_expand/src/mbe/diagnostics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub(super) fn failed_to_match_macro<'cx>(
3737
tracker
3838
.cx
3939
.dcx()
40-
.span_delayed_bug(sp, "Macro matching returned a success on the second try");
40+
.span_assert_has_errors(sp, "Macro matching returned a success on the second try");
4141
}
4242

4343
if let Some(result) = tracker.result {
@@ -154,7 +154,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
154154
Success(_) => {
155155
// Nonterminal parser recovery might turn failed matches into successful ones,
156156
// but for that it must have emitted an error already
157-
self.cx.dcx().span_delayed_bug(
157+
self.cx.dcx().span_assert_has_errors(
158158
self.root_span,
159159
"should not collect detailed info for successful macro match",
160160
);

Diff for: compiler/rustc_hir_analysis/src/astconv/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
758758
// since we should have emitten an error for them earlier, and they will
759759
// not be well-formed!
760760
if polarity == ty::ImplPolarity::Negative {
761-
self.tcx().dcx().span_delayed_bug(
761+
self.tcx().dcx().span_assert_has_errors(
762762
binding.span,
763763
"negative trait bounds should not have bindings",
764764
);
@@ -1294,7 +1294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12941294
// trait reference.
12951295
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
12961296
// A cycle error occurred, most likely.
1297-
let guar = tcx.dcx().span_delayed_bug(span, "expected cycle error");
1297+
let guar = tcx.dcx().span_assert_has_errors(span, "expected cycle error");
12981298
return Err(guar);
12991299
};
13001300

Diff for: compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
329329
false
330330
});
331331
if references_self {
332-
let guar = tcx.dcx().span_delayed_bug(
332+
let guar = tcx.dcx().span_assert_has_errors(
333333
span,
334334
"trait object projection bounds reference `Self`",
335335
);

0 commit comments

Comments
 (0)