From 185ac52c2e5f3b2c091aa587ee49b1437887d61e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Aug 2026 15:11:16 +1000 Subject: [PATCH 1/3] Fix inconsistency in backward handling of `Yield` For `Call` and `InlineAsm` we currently pass `pred` to `apply_call_return_effect`, but for `Yield` we pass `block`. This appears to be a copy/paste error. This currently has no effect because no existing backward analyses look at this argument, but it's worth fixing. There's also a similar case in graphviz.rs. --- compiler/rustc_mir_dataflow/src/framework/direction.rs | 2 +- compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 74962a809247b..07e0fa6108dc9 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -111,7 +111,7 @@ impl Direction for Backward { let mut tmp = exit_state.clone(); analysis.apply_call_return_effect( &mut tmp, - block, + pred, CallReturnPlaces::Yield(resume_arg), ); propagate(pred, &tmp); diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 4996841703d16..be572eab929bc 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -393,13 +393,13 @@ where })?; } - mir::TerminatorKind::Yield { resume, resume_arg, .. } => { + mir::TerminatorKind::Yield { resume_arg, .. } => { self.write_row(w, "", "(on yield resume)", |this, w, fmt| { let state_on_coroutine_drop = this.cursor.get().clone(); this.cursor.apply_custom_effect(|analysis, state| { analysis.apply_call_return_effect( state, - resume, + block, CallReturnPlaces::Yield(resume_arg), ); }); From 828faaad0ac56d9971f21e9b569ee273833b5df4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Aug 2026 15:15:23 +1000 Subject: [PATCH 2/3] Improve edge computation in `Backward::apply_effects_in_block` The edge computation for `Call`, `InlineAsm`, and `Yield` exactly duplicates what is done by `TerminatorKind::edges()`. This commit changes it to use `edges()`; this makes the backward analysis more similar to the forward analysis, which also matches on `TerminatorEdges`. Note: the bug fixed in the previous commit would have been less likely with this new code. --- .../src/framework/direction.rs | 40 +++---------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 07e0fa6108dc9..2c66be5dc8f8b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,5 +1,5 @@ use rustc_middle::bug; -use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges}; +use rustc_middle::mir::{self, BasicBlock, Location, TerminatorEdges}; use super::visitor::ResultsVisitor; use super::{Analysis, Effect, EffectIndex, SwitchTargetIndex}; @@ -79,45 +79,17 @@ impl Direction for Backward { let exit_state = state; for pred in body.basic_blocks.predecessors()[block].iter().copied() { - match body[pred].terminator().kind { + match body[pred].terminator().edges() { // Apply terminator-specific edge effects. - mir::TerminatorKind::Call { destination, target: Some(dest), .. } - if dest == block => + TerminatorEdges::AssignOnReturn { return_, place, .. } + if return_.contains(&block) => { let mut tmp = exit_state.clone(); - analysis.apply_call_return_effect( - &mut tmp, - pred, - CallReturnPlaces::Call(destination), - ); - propagate(pred, &tmp); - } - - mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } - if targets.contains(&block) => - { - let mut tmp = exit_state.clone(); - analysis.apply_call_return_effect( - &mut tmp, - pred, - CallReturnPlaces::InlineAsm(operands), - ); - propagate(pred, &tmp); - } - - mir::TerminatorKind::Yield { resume, drop, resume_arg, .. } - if resume == block || drop == Some(block) => - { - let mut tmp = exit_state.clone(); - analysis.apply_call_return_effect( - &mut tmp, - pred, - CallReturnPlaces::Yield(resume_arg), - ); + analysis.apply_call_return_effect(&mut tmp, pred, place); propagate(pred, &tmp); } - mir::TerminatorKind::SwitchInt { ref targets, ref discr } => { + TerminatorEdges::SwitchInt { targets, discr } => { if let Some(_data) = analysis.get_switch_int_data(pred, targets, discr) { bug!( "SwitchInt edge effects are unsupported in backward dataflow analyses" From ea4322dc6a1b75c675c3351a87b505f19c373bf9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Aug 2026 15:34:38 +1000 Subject: [PATCH 3/3] De-`mut` an `apply_switch_int_edge_effect` argument It doesn't need to be `mut`. --- compiler/rustc_mir_dataflow/src/framework/direction.rs | 6 +++--- compiler/rustc_mir_dataflow/src/framework/mod.rs | 2 +- compiler/rustc_mir_dataflow/src/impls/initialized.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 2c66be5dc8f8b..f8eeb9dfcb43c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -192,12 +192,12 @@ impl Direction for Forward { } } TerminatorEdges::SwitchInt { targets, discr } => { - if let Some(mut data) = analysis.get_switch_int_data(block, targets, discr) { + if let Some(data) = analysis.get_switch_int_data(block, targets, discr) { let mut tmp = analysis.bottom_value(body); for (i, (_value, target)) in targets.iter().enumerate() { tmp.clone_from(exit_state); let target_idx = SwitchTargetIndex::Normal(i); - analysis.apply_switch_int_edge_effect(&mut tmp, &mut data, target_idx); + analysis.apply_switch_int_edge_effect(&mut tmp, &data, target_idx); propagate(target, &tmp); } @@ -206,7 +206,7 @@ impl Direction for Forward { // a clone of the dataflow state. analysis.apply_switch_int_edge_effect( exit_state, - &mut data, + &data, SwitchTargetIndex::Otherwise, ); propagate(targets.otherwise(), exit_state); diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index a72bb3494be4c..6cdbf11f22e59 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -264,7 +264,7 @@ pub trait Analysis<'tcx> { fn apply_switch_int_edge_effect( &self, _state: &mut Self::Domain, - _data: &mut Self::SwitchIntData, + _data: &Self::SwitchIntData, _target_idx: SwitchTargetIndex, ) { unreachable!(); diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 1b2c58c7e514c..7356a0815a8fc 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -458,7 +458,7 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { fn apply_switch_int_edge_effect( &self, state: &mut Self::Domain, - data: &mut Self::SwitchIntData, + data: &Self::SwitchIntData, target_idx: SwitchTargetIndex, ) { let inactive_variants = match target_idx { @@ -588,7 +588,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn apply_switch_int_edge_effect( &self, state: &mut Self::Domain, - data: &mut Self::SwitchIntData, + data: &Self::SwitchIntData, target_idx: SwitchTargetIndex, ) { let inactive_variants = match target_idx {