Skip to content

Commit deaf307

Browse files
committed
Make broken MIR a proper lint.
1 parent 915e535 commit deaf307

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ declare_lint_pass! {
2727
BARE_TRAIT_OBJECTS,
2828
BINDINGS_WITH_VARIANT_NAME,
2929
BREAK_WITH_LABEL_AND_LOOP,
30+
BROKEN_MIR,
3031
COHERENCE_LEAK_CHECK,
3132
CONFLICTING_REPR_HINTS,
3233
CONST_EVALUATABLE_UNCHECKED,
@@ -3695,6 +3696,15 @@ declare_lint! {
36953696
"`break` expression with label and unlabeled loop as value expression"
36963697
}
36973698

3699+
crate::declare_tool_lint! {
3700+
/// The `broken_mir` statically detects undefined behaviour in the MIR optimization pipeline.
3701+
/// This is an internal lint, and not intended to be used directly.
3702+
pub rustc::BROKEN_MIR,
3703+
Deny,
3704+
"broken MIR",
3705+
report_in_external_macro: true
3706+
}
3707+
36983708
declare_lint! {
36993709
/// The `non_exhaustive_omitted_patterns` lint aims to help consumers of a `#[non_exhaustive]`
37003710
/// struct or enum who want to match all of its fields/variants explicitly.

compiler/rustc_mir_transform/src/lint.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
use std::borrow::Cow;
66

77
use rustc_data_structures::fx::FxHashSet;
8+
use rustc_hir::{CRATE_HIR_ID, HirId};
89
use rustc_index::bit_set::DenseBitSet;
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, always_storage_live_locals};
1314
use rustc_mir_dataflow::{Analysis, ResultsCursor};
15+
use rustc_session::lint::builtin::BROKEN_MIR;
1416

1517
pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
1618
let always_live_locals = &always_storage_live_locals(body);
@@ -27,6 +29,11 @@ pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String
2729
tcx,
2830
when,
2931
body,
32+
lint_id: body
33+
.source
34+
.def_id()
35+
.as_local()
36+
.map_or(CRATE_HIR_ID, |def_id| tcx.local_def_id_to_hir_id(def_id)),
3037
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
3138
always_live_locals,
3239
maybe_storage_live,
@@ -42,6 +49,7 @@ struct Lint<'a, 'tcx> {
4249
tcx: TyCtxt<'tcx>,
4350
when: String,
4451
body: &'a Body<'tcx>,
52+
lint_id: HirId,
4553
is_fn_like: bool,
4654
always_live_locals: &'a DenseBitSet<Local>,
4755
maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
@@ -50,19 +58,19 @@ struct Lint<'a, 'tcx> {
5058
}
5159

5260
impl<'a, 'tcx> Lint<'a, 'tcx> {
53-
#[track_caller]
61+
#[allow(rustc::untranslatable_diagnostic)]
62+
#[allow(rustc::diagnostic_outside_of_impl)]
5463
fn fail(&self, location: Location, msg: impl AsRef<str>) {
5564
let span = self.body.source_info(location).span;
56-
self.tcx.sess.dcx().span_delayed_bug(
57-
span,
58-
format!(
65+
self.tcx.node_span_lint(BROKEN_MIR, self.lint_id, span, |lint| {
66+
lint.primary_message(format!(
5967
"broken MIR in {:?} ({}) at {:?}:\n{}",
6068
self.body.source.instance,
6169
self.when,
6270
location,
6371
msg.as_ref()
64-
),
65-
);
72+
));
73+
});
6674
}
6775
}
6876

tests/mir-opt/reference_prop.rs

Lines changed: 4 additions & 2 deletions
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(core_intrinsics, custom_mir)]
4+
#![feature(core_intrinsics, custom_mir, lint_reasons)]
65

76
#[inline(never)]
87
fn opaque(_: impl Sized) {}
@@ -677,6 +676,7 @@ fn read_through_raw(x: &mut usize) -> usize {
677676
}
678677

679678
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
679+
#[expect(rustc::broken_mir)]
680680
fn multiple_storage() {
681681
// CHECK-LABEL: multiple_storage
682682
// CHECK: _3 = copy (*_2);
@@ -703,6 +703,7 @@ fn multiple_storage() {
703703
}
704704

705705
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
706+
#[expect(rustc::broken_mir)]
706707
fn dominate_storage() {
707708
// CHECK-LABEL: dominate_storage
708709
// CHECK: _5 = copy (*_2);
@@ -733,6 +734,7 @@ fn dominate_storage() {
733734
}
734735

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

0 commit comments

Comments
 (0)