From deaf307925a1ca0d9d4b1dad46fa2baf7a7095a0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 23 Dec 2023 13:39:09 +0000 Subject: [PATCH 1/3] Make broken MIR a proper lint. --- compiler/rustc_lint_defs/src/builtin.rs | 10 ++++++++++ compiler/rustc_mir_transform/src/lint.rs | 20 ++++++++++++++------ tests/mir-opt/reference_prop.rs | 6 ++++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 15f0bad226d27..2481e8e3d70a9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -27,6 +27,7 @@ declare_lint_pass! { BARE_TRAIT_OBJECTS, BINDINGS_WITH_VARIANT_NAME, BREAK_WITH_LABEL_AND_LOOP, + BROKEN_MIR, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED, @@ -3695,6 +3696,15 @@ declare_lint! { "`break` expression with label and unlabeled loop as value expression" } +crate::declare_tool_lint! { + /// The `broken_mir` statically detects undefined behaviour in the MIR optimization pipeline. + /// This is an internal lint, and not intended to be used directly. + pub rustc::BROKEN_MIR, + Deny, + "broken MIR", + report_in_external_macro: true +} + declare_lint! { /// The `non_exhaustive_omitted_patterns` lint aims to help consumers of a `#[non_exhaustive]` /// struct or enum who want to match all of its fields/variants explicitly. diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index f472c7cb493d0..4cb6d4ff2dc37 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -5,12 +5,14 @@ use std::borrow::Cow; use rustc_data_structures::fx::FxHashSet; +use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive, always_storage_live_locals}; use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use rustc_session::lint::builtin::BROKEN_MIR; pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { 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 tcx, when, body, + lint_id: body + .source + .def_id() + .as_local() + .map_or(CRATE_HIR_ID, |def_id| tcx.local_def_id_to_hir_id(def_id)), is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(), always_live_locals, maybe_storage_live, @@ -42,6 +49,7 @@ struct Lint<'a, 'tcx> { tcx: TyCtxt<'tcx>, when: String, body: &'a Body<'tcx>, + lint_id: HirId, is_fn_like: bool, always_live_locals: &'a DenseBitSet, maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, @@ -50,19 +58,19 @@ struct Lint<'a, 'tcx> { } impl<'a, 'tcx> Lint<'a, 'tcx> { - #[track_caller] + #[allow(rustc::untranslatable_diagnostic)] + #[allow(rustc::diagnostic_outside_of_impl)] fn fail(&self, location: Location, msg: impl AsRef) { let span = self.body.source_info(location).span; - self.tcx.sess.dcx().span_delayed_bug( - span, - format!( + self.tcx.node_span_lint(BROKEN_MIR, self.lint_id, span, |lint| { + lint.primary_message(format!( "broken MIR in {:?} ({}) at {:?}:\n{}", self.body.source.instance, self.when, location, msg.as_ref() - ), - ); + )); + }); } } diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 00d4893807163..8a9a29ca1790e 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -1,8 +1,7 @@ -//@ compile-flags: -Zlint-mir=no //@ test-mir-pass: ReferencePropagation //@ needs-unwind -#![feature(core_intrinsics, custom_mir)] +#![feature(core_intrinsics, custom_mir, lint_reasons)] #[inline(never)] fn opaque(_: impl Sized) {} @@ -677,6 +676,7 @@ fn read_through_raw(x: &mut usize) -> usize { } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] +#[expect(rustc::broken_mir)] fn multiple_storage() { // CHECK-LABEL: multiple_storage // CHECK: _3 = copy (*_2); @@ -703,6 +703,7 @@ fn multiple_storage() { } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] +#[expect(rustc::broken_mir)] fn dominate_storage() { // CHECK-LABEL: dominate_storage // CHECK: _5 = copy (*_2); @@ -733,6 +734,7 @@ fn dominate_storage() { } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] +#[expect(rustc::broken_mir)] fn maybe_dead(m: bool) { // CHECK-LABEL: fn maybe_dead( // CHECK: (*_5) = const 7_i32; From 9efb83d45de2e567456cd0683402267fdd5937fe Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 23 Dec 2023 18:23:18 +0000 Subject: [PATCH 2/3] Bless ui test. --- tests/ui/mir/lint/storage-live.stderr | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/ui/mir/lint/storage-live.stderr b/tests/ui/mir/lint/storage-live.stderr index 50df9ae061fcc..81c16e75e8ca9 100644 --- a/tests/ui/mir/lint/storage-live.stderr +++ b/tests/ui/mir/lint/storage-live.stderr @@ -5,15 +5,11 @@ error: internal compiler error: broken MIR in Item(DefId(0:8 ~ storage_live[HASH LL | StorageLive(a); | ^^^^^^^^^^^^^^ | -note: delayed at compiler/rustc_mir_transform/src/lint.rs:LL:CC - disabled backtrace - --> $DIR/storage-live.rs:21:13 - | -LL | StorageLive(a); - | ^^^^^^^^^^^^^^ - - + = aborting due to `-Z treat-err-as-bug=1` error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -end of query stack +#0 [mir_built] building MIR for `multiple_storage` +#1 [has_ffi_unwind_calls] checking if `multiple_storage` contains FFI-unwind calls +... and 3 other queries... use `env RUST_BACKTRACE=1` to see the full query stack From 317dc210ff3b6b0456779cdd66b8d72486658ee6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 1 Jan 2024 01:56:50 +0000 Subject: [PATCH 3/3] Register lint with internal lints. --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint_defs/src/builtin.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 48982bda0a08d..d976393493129 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -657,6 +657,7 @@ fn register_internals(store: &mut LintStore) { "rustc::internal", None, vec![ + LintId::of(BROKEN_MIR), LintId::of(DEFAULT_HASH_TYPES), LintId::of(POTENTIAL_QUERY_INSTABILITY), LintId::of(UNTRACKED_QUERY_INFORMATION), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2481e8e3d70a9..bfb5ea4e2be5a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -27,7 +27,6 @@ declare_lint_pass! { BARE_TRAIT_OBJECTS, BINDINGS_WITH_VARIANT_NAME, BREAK_WITH_LABEL_AND_LOOP, - BROKEN_MIR, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED,