Skip to content

Commit 1c121fb

Browse files
committed
Make broken MIR a proper lint.
1 parent a604303 commit 1c121fb

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ declare_lint_pass! {
2626
BARE_TRAIT_OBJECTS,
2727
BINDINGS_WITH_VARIANT_NAME,
2828
BREAK_WITH_LABEL_AND_LOOP,
29+
BROKEN_MIR,
2930
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
3031
CENUM_IMPL_DROP_CAST,
3132
COHERENCE_LEAK_CHECK,
@@ -3933,6 +3934,15 @@ declare_lint! {
39333934
"`break` expression with label and unlabeled loop as value expression"
39343935
}
39353936

3937+
crate::declare_tool_lint! {
3938+
/// The `broken_mir` statically detects undefined behaviour in the MIR optimization pipeline.
3939+
/// This is an internal lint, and not intended to be used directly.
3940+
pub rustc::BROKEN_MIR,
3941+
Deny,
3942+
"broken MIR",
3943+
report_in_external_macro: true
3944+
}
3945+
39363946
declare_lint! {
39373947
/// The `non_exhaustive_omitted_patterns` lint aims to help consumers of a `#[non_exhaustive]`
39383948
/// struct or enum who want to match all of its fields/variants explicitly.

compiler/rustc_mir_transform/src/lint.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
use std::borrow::Cow;
66

77
use rustc_data_structures::fx::FxHashSet;
8+
use rustc_hir::{HirId, CRATE_HIR_ID};
89
use rustc_index::bit_set::BitSet;
910
use rustc_middle::mir::visit::{PlaceContext, Visitor};
1011
use rustc_middle::mir::*;
1112
use rustc_middle::ty::TyCtxt;
1213
use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive};
1314
use rustc_mir_dataflow::storage::always_storage_live_locals;
1415
use rustc_mir_dataflow::{Analysis, ResultsCursor};
16+
use rustc_session::lint::builtin::BROKEN_MIR;
1517

1618
pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
1719
let always_live_locals = &always_storage_live_locals(body);
@@ -30,6 +32,11 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
3032
tcx,
3133
when,
3234
body,
35+
lint_id: body
36+
.source
37+
.def_id()
38+
.as_local()
39+
.map_or(CRATE_HIR_ID, |def_id| tcx.local_def_id_to_hir_id(def_id)),
3340
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
3441
always_live_locals,
3542
maybe_storage_live,
@@ -45,6 +52,7 @@ struct Lint<'a, 'tcx> {
4552
tcx: TyCtxt<'tcx>,
4653
when: String,
4754
body: &'a Body<'tcx>,
55+
lint_id: HirId,
4856
is_fn_like: bool,
4957
always_live_locals: &'a BitSet<Local>,
5058
maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
@@ -53,19 +61,19 @@ struct Lint<'a, 'tcx> {
5361
}
5462

5563
impl<'a, 'tcx> Lint<'a, 'tcx> {
56-
#[track_caller]
64+
#[allow(rustc::untranslatable_diagnostic)]
65+
#[allow(rustc::diagnostic_outside_of_impl)]
5766
fn fail(&self, location: Location, msg: impl AsRef<str>) {
5867
let span = self.body.source_info(location).span;
59-
self.tcx.sess.dcx().span_delayed_bug(
60-
span,
61-
format!(
68+
self.tcx.node_span_lint(BROKEN_MIR, self.lint_id, span, |lint| {
69+
lint.primary_message(format!(
6270
"broken MIR in {:?} ({}) at {:?}:\n{}",
6371
self.body.source.instance,
6472
self.when,
6573
location,
6674
msg.as_ref()
67-
),
68-
);
75+
));
76+
});
6977
}
7078
}
7179

tests/mir-opt/reference_prop.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
//@ compile-flags: -Zlint-mir=no
21
//@ test-mir-pass: ReferencePropagation
32
//@ needs-unwind
43

5-
#![feature(raw_ref_op)]
4+
#![feature(raw_ref_op, lint_reasons)]
65
#![feature(core_intrinsics, custom_mir)]
76

87
#[inline(never)]
@@ -678,6 +677,7 @@ fn read_through_raw(x: &mut usize) -> usize {
678677
}
679678

680679
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
680+
#[expect(rustc::broken_mir)]
681681
fn multiple_storage() {
682682
// CHECK-LABEL: multiple_storage
683683
// CHECK: _3 = (*_2);
@@ -704,6 +704,7 @@ fn multiple_storage() {
704704
}
705705

706706
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
707+
#[expect(rustc::broken_mir)]
707708
fn dominate_storage() {
708709
// CHECK-LABEL: dominate_storage
709710
// CHECK: _5 = (*_2);
@@ -734,6 +735,7 @@ fn dominate_storage() {
734735
}
735736

736737
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
738+
#[expect(rustc::broken_mir)]
737739
fn maybe_dead(m: bool) {
738740
// CHECK-LABEL: fn maybe_dead(
739741
// CHECK: (*_5) = const 7_i32;

0 commit comments

Comments
 (0)