Skip to content

Commit bc602ce

Browse files
committed
Make broken MIR a proper lint.
1 parent e51e98d commit bc602ce

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

compiler/rustc_lint_defs/src/builtin.rs

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ declare_lint_pass! {
2323
BARE_TRAIT_OBJECTS,
2424
BINDINGS_WITH_VARIANT_NAME,
2525
BREAK_WITH_LABEL_AND_LOOP,
26+
BROKEN_MIR,
2627
BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
2728
CENUM_IMPL_DROP_CAST,
2829
COHERENCE_LEAK_CHECK,
@@ -3955,6 +3956,15 @@ declare_lint! {
39553956
"`break` expression with label and unlabeled loop as value expression"
39563957
}
39573958

3959+
crate::declare_tool_lint! {
3960+
/// The `broken_mir` statically detects undefined behaviour in the MIR optimization pipeline.
3961+
/// This is an internal lint, and not intended to be used directly.
3962+
pub rustc::BROKEN_MIR,
3963+
Deny,
3964+
"broken MIR",
3965+
report_in_external_macro: true
3966+
}
3967+
39583968
declare_lint! {
39593969
/// The `non_exhaustive_omitted_patterns` lint aims to help consumers of a `#[non_exhaustive]`
39603970
/// struct or enum who want to match all of its fields/variants explicitly.

compiler/rustc_mir_transform/src/lint.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
//! This pass statically detects code which has undefined behaviour or is likely to be erroneous.
22
//! It can be used to locate problems in MIR building or optimizations. It assumes that all code
33
//! can be executed, so it has false positives.
4+
5+
use rustc_hir::{HirId, CRATE_HIR_ID};
46
use rustc_index::bit_set::BitSet;
57
use rustc_middle::mir::visit::{PlaceContext, Visitor};
68
use rustc_middle::mir::*;
79
use rustc_middle::ty::TyCtxt;
810
use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive};
911
use rustc_mir_dataflow::storage::always_storage_live_locals;
1012
use rustc_mir_dataflow::{Analysis, ResultsCursor};
13+
use rustc_session::lint::builtin::BROKEN_MIR;
1114
use std::borrow::Cow;
1215

1316
pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
@@ -28,6 +31,11 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
2831
tcx,
2932
when,
3033
body,
34+
lint_id: body
35+
.source
36+
.def_id()
37+
.as_local()
38+
.map_or(CRATE_HIR_ID, |def_id| tcx.local_def_id_to_hir_id(def_id)),
3139
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
3240
always_live_locals,
3341
reachable_blocks,
@@ -41,6 +49,7 @@ struct Lint<'a, 'tcx> {
4149
tcx: TyCtxt<'tcx>,
4250
when: String,
4351
body: &'a Body<'tcx>,
52+
lint_id: HirId,
4453
is_fn_like: bool,
4554
always_live_locals: &'a BitSet<Local>,
4655
reachable_blocks: BitSet<BasicBlock>,
@@ -49,10 +58,13 @@ struct Lint<'a, 'tcx> {
4958
}
5059

5160
impl<'a, 'tcx> Lint<'a, 'tcx> {
52-
#[track_caller]
61+
#[allow(rustc::untranslatable_diagnostic)]
62+
#[allow(rustc::diagnostic_outside_of_impl)]
5363
fn fail(&self, location: Location, msg: impl AsRef<str>) {
5464
let span = self.body.source_info(location).span;
55-
self.tcx.sess.dcx().span_delayed_bug(
65+
self.tcx.struct_span_lint_hir(
66+
BROKEN_MIR,
67+
self.lint_id,
5668
span,
5769
format!(
5870
"broken MIR in {:?} ({}) at {:?}:\n{}",
@@ -61,6 +73,7 @@ impl<'a, 'tcx> Lint<'a, 'tcx> {
6173
location,
6274
msg.as_ref()
6375
),
76+
|_| {},
6477
);
6578
}
6679
}

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
// unit-test: 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)]
@@ -680,6 +679,7 @@ fn read_through_raw(x: &mut usize) -> usize {
680679
}
681680

682681
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
682+
#[expect(rustc::broken_mir)]
683683
fn multiple_storage() {
684684
// CHECK-LABEL: multiple_storage
685685
// CHECK: _3 = (*_2);
@@ -706,6 +706,7 @@ fn multiple_storage() {
706706
}
707707

708708
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
709+
#[expect(rustc::broken_mir)]
709710
fn dominate_storage() {
710711
// CHECK-LABEL: dominate_storage
711712
// CHECK: _5 = (*_2);
@@ -736,6 +737,7 @@ fn dominate_storage() {
736737
}
737738

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

0 commit comments

Comments
 (0)