From 36bf31df2b2a2538ec693ed6dac3d8202fb56a54 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 1 Aug 2025 15:31:16 +0200 Subject: [PATCH 1/2] fix `#[loop_match]` on diverging loop this generated invalid MIR before --- .../rustc_mir_build/src/builder/expr/into.rs | 2 +- tests/ui/loop-match/diverges.rs | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/ui/loop-match/diverges.rs diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 82b883a99a11c..ac87f671699db 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -345,7 +345,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, |this| { this.lower_match_arms( - destination, + state_place, scrutinee_place_builder, scrutinee_span, arms, diff --git a/tests/ui/loop-match/diverges.rs b/tests/ui/loop-match/diverges.rs new file mode 100644 index 0000000000000..f1b3ffb2076bd --- /dev/null +++ b/tests/ui/loop-match/diverges.rs @@ -0,0 +1,44 @@ +//@ build-pass +//@ compile-flags: -Zvalidate-mir +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +// Test that a #[loop_match] without an explicit break from the loop generates valid MIR. + +fn break_to_block_unit() -> u8 { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + _ => 'b: { + break 'b 2; + } + } + } + } +} + +fn break_to_block_value() -> u8 { + let mut state = 0u8; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + _ => break 'blk state, + } + } + } +} + +fn infinite_a(mut state: u8) { + #[loop_match] + loop { + state = 'blk: { + match state { + a => a, + } + } + } +} From f0c20975d1c320bce2510f28bcecc68adf877e35 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 1 Aug 2025 16:15:21 +0200 Subject: [PATCH 2/2] add place mention for `#[loop_match]` scrutinee --- compiler/rustc_mir_build/src/builder/expr/into.rs | 6 ++++-- compiler/rustc_mir_build/src/builder/matches/mod.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index ac87f671699db..78bcc47d9d0de 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -295,9 +295,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.diverge_from(loop_block); // Logic for `match`. - let scrutinee_place_builder = - unpack!(body_block = this.as_place_builder(body_block, scrutinee)); let scrutinee_span = this.thir.exprs[scrutinee].span; + let scrutinee_place_builder = unpack!( + body_block = this.lower_scrutinee(body_block, scrutinee, scrutinee_span) + ); + let match_start_span = match_span.shrink_to_lo().to(scrutinee_span); let mut patterns = Vec::with_capacity(arms.len()); diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 2c29b8628417f..e863f94af7ea0 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -407,7 +407,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /// Evaluate the scrutinee and add the PlaceMention for it. - fn lower_scrutinee( + pub(crate) fn lower_scrutinee( &mut self, mut block: BasicBlock, scrutinee_id: ExprId,