diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 804b44a6bf05d..fe9384300d4ce 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -55,7 +55,7 @@ pub trait Direction { body: &mir::Body<'tcx>, exit_state: &mut A::Domain, block: (BasicBlock, &'_ mir::BasicBlockData<'tcx>), - propagate: impl FnMut(BasicBlock, &A::Domain), + propagate: impl FnMut(&mut A, BasicBlock, &A::Domain), ) where A: Analysis<'tcx>; } @@ -221,7 +221,7 @@ impl Direction for Backward { body: &mir::Body<'tcx>, exit_state: &mut A::Domain, (bb, _bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>), - mut propagate: impl FnMut(BasicBlock, &A::Domain), + mut propagate: impl FnMut(&mut A, BasicBlock, &A::Domain), ) where A: Analysis<'tcx>, { @@ -237,7 +237,7 @@ impl Direction for Backward { pred, CallReturnPlaces::Call(destination), ); - propagate(pred, &tmp); + propagate(analysis, pred, &tmp); } mir::TerminatorKind::InlineAsm { @@ -249,13 +249,13 @@ impl Direction for Backward { pred, CallReturnPlaces::InlineAsm(operands), ); - propagate(pred, &tmp); + propagate(analysis, pred, &tmp); } mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == bb => { let mut tmp = exit_state.clone(); analysis.apply_yield_resume_effect(&mut tmp, resume, resume_arg); - propagate(pred, &tmp); + propagate(analysis, pred, &tmp); } mir::TerminatorKind::SwitchInt { targets: _, ref discr } => { @@ -271,11 +271,11 @@ impl Direction for Backward { analysis.apply_switch_int_edge_effects(pred, discr, &mut applier); if !applier.effects_applied { - propagate(pred, exit_state) + propagate(analysis, pred, exit_state) } } - _ => propagate(pred, exit_state), + _ => propagate(analysis, pred, exit_state), } } } @@ -290,12 +290,17 @@ struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> { effects_applied: bool, } -impl super::SwitchIntEdgeEffects for BackwardSwitchIntEdgeEffectsApplier<'_, '_, D, F> +impl<'tcx, A, F> super::SwitchIntEdgeEffects<'tcx, A> + for BackwardSwitchIntEdgeEffectsApplier<'_, '_, A::Domain, F> where - D: Clone, - F: FnMut(BasicBlock, &D), + A: Analysis<'tcx>, + F: FnMut(&mut A, BasicBlock, &A::Domain), { - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { + fn apply( + &mut self, + analysis: &mut A, + mut apply_edge_effect: impl FnMut(&mut A, &mut A::Domain, SwitchIntTarget), + ) { assert!(!self.effects_applied); let values = &self.body.basic_blocks.switch_sources()[&(self.bb, self.pred)]; @@ -304,8 +309,8 @@ where let mut tmp = None; for target in targets { let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); - apply_edge_effect(tmp, target); - (self.propagate)(self.pred, tmp); + apply_edge_effect(analysis, tmp, target); + (self.propagate)(analysis, self.pred, tmp); } self.effects_applied = true; @@ -468,7 +473,7 @@ impl Direction for Forward { _body: &mir::Body<'tcx>, exit_state: &mut A::Domain, (bb, bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>), - mut propagate: impl FnMut(BasicBlock, &A::Domain), + mut propagate: impl FnMut(&mut A, BasicBlock, &A::Domain), ) where A: Analysis<'tcx>, { @@ -476,35 +481,35 @@ impl Direction for Forward { match bb_data.terminator().kind { Return | Resume | Terminate | GeneratorDrop | Unreachable => {} - Goto { target } => propagate(target, exit_state), + Goto { target } => propagate(analysis, target, exit_state), Assert { target, unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _, replace: _ } | FalseUnwind { real_target: target, unwind } => { if let UnwindAction::Cleanup(unwind) = unwind { - propagate(unwind, exit_state); + propagate(analysis, unwind, exit_state); } - propagate(target, exit_state); + propagate(analysis, target, exit_state); } FalseEdge { real_target, imaginary_target } => { - propagate(real_target, exit_state); - propagate(imaginary_target, exit_state); + propagate(analysis, real_target, exit_state); + propagate(analysis, imaginary_target, exit_state); } Yield { resume: target, drop, resume_arg, value: _ } => { if let Some(drop) = drop { - propagate(drop, exit_state); + propagate(analysis, drop, exit_state); } analysis.apply_yield_resume_effect(exit_state, target, resume_arg); - propagate(target, exit_state); + propagate(analysis, target, exit_state); } Call { unwind, destination, target, func: _, args: _, call_source: _, fn_span: _ } => { if let UnwindAction::Cleanup(unwind) = unwind { - propagate(unwind, exit_state); + propagate(analysis, unwind, exit_state); } if let Some(target) = target { @@ -515,7 +520,7 @@ impl Direction for Forward { bb, CallReturnPlaces::Call(destination), ); - propagate(target, exit_state); + propagate(analysis, target, exit_state); } } @@ -528,7 +533,7 @@ impl Direction for Forward { unwind, } => { if let UnwindAction::Cleanup(unwind) = unwind { - propagate(unwind, exit_state); + propagate(analysis, unwind, exit_state); } if let Some(target) = destination { @@ -539,7 +544,7 @@ impl Direction for Forward { bb, CallReturnPlaces::InlineAsm(operands), ); - propagate(target, exit_state); + propagate(analysis, target, exit_state); } } @@ -562,7 +567,7 @@ impl Direction for Forward { if !effects_applied { for target in targets.all_targets() { - propagate(*target, exit_state); + propagate(analysis, *target, exit_state); } } } @@ -578,26 +583,35 @@ struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { effects_applied: bool, } -impl super::SwitchIntEdgeEffects for ForwardSwitchIntEdgeEffectsApplier<'_, D, F> +impl<'tcx, A, F> super::SwitchIntEdgeEffects<'tcx, A> + for ForwardSwitchIntEdgeEffectsApplier<'_, A::Domain, F> where - D: Clone, - F: FnMut(BasicBlock, &D), + A: Analysis<'tcx>, + F: FnMut(&mut A, BasicBlock, &A::Domain), { - fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) { + fn apply( + &mut self, + analysis: &mut A, + mut apply_edge_effect: impl FnMut(&mut A, &mut A::Domain, SwitchIntTarget), + ) { assert!(!self.effects_applied); let mut tmp = None; for (value, target) in self.targets.iter() { let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); - apply_edge_effect(tmp, SwitchIntTarget { value: Some(value), target }); - (self.propagate)(target, tmp); + apply_edge_effect(analysis, tmp, SwitchIntTarget { value: Some(value), target }); + (self.propagate)(analysis, target, tmp); } // Once we get to the final, "otherwise" branch, there is no need to preserve `exit_state`, // so pass it directly to `apply_edge_effect` to save a clone of the dataflow state. let otherwise = self.targets.otherwise(); - apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); - (self.propagate)(otherwise, self.exit_state); + apply_edge_effect( + analysis, + self.exit_state, + SwitchIntTarget { value: None, target: otherwise }, + ); + (self.propagate)(analysis, otherwise, self.exit_state); self.effects_applied = true; } diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index c755d7588c254..465031abf00b2 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -25,8 +25,7 @@ use super::fmt::DebugWithContext; use super::graphviz; use super::{ visit_results, Analysis, AnalysisDomain, CloneAnalysis, Direction, GenKill, GenKillAnalysis, - GenKillSet, JoinSemiLattice, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitor, + GenKillSet, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, ResultsVisitor, }; pub type EntrySets<'tcx, A> = IndexVec>::Domain>; @@ -150,7 +149,7 @@ where impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> where A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, - D: Clone + JoinSemiLattice + GenKill + BitSetExt, + D: Clone + GenKill + BitSetExt, T: Idx, { /// Creates a new `Engine` to solve a gen-kill dataflow problem. @@ -181,10 +180,9 @@ where } } -impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> +impl<'a, 'tcx, A> Engine<'a, 'tcx, A> where - A: Analysis<'tcx, Domain = D>, - D: Clone + JoinSemiLattice, + A: Analysis<'tcx>, { /// Creates a new `Engine` to solve a dataflow problem with an arbitrary transfer /// function. @@ -276,8 +274,8 @@ where body, &mut state, (bb, bb_data), - |target: BasicBlock, state: &A::Domain| { - let set_changed = entry_sets[target].join(state); + |analysis: &mut A, target: BasicBlock, state: &A::Domain| { + let set_changed = analysis.join(&mut entry_sets[target], state, target); if set_changed { dirty_queue.insert(target); } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 58df9b9a768b5..d65a1b16c6578 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -102,7 +102,7 @@ impl BitSetExt for ChunkedBitSet { /// initial value at the entry point of each basic block. pub trait AnalysisDomain<'tcx> { /// The type that holds the dataflow state at any given point in the program. - type Domain: Clone + JoinSemiLattice; + type Domain: Clone + Eq; /// The direction of this analysis. Either `Forward` or `Backward`. type Direction: Direction = Forward; @@ -127,6 +127,21 @@ pub trait AnalysisDomain<'tcx> { fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain); } +/// Gets the context under which to perform a join. +pub trait AnalysisJoin<'tcx>: AnalysisDomain<'tcx> { + fn join(&mut self, state: &mut Self::Domain, other: &Self::Domain, loc: BasicBlock) -> bool; +} + +impl<'tcx, T> AnalysisJoin<'tcx> for T +where + T: ?Sized + AnalysisDomain<'tcx>, + >::Domain: JoinSemiLattice, +{ + fn join(&mut self, state: &mut Self::Domain, other: &Self::Domain, _: BasicBlock) -> bool { + state.join(other) + } +} + /// A dataflow problem with an arbitrarily complex transfer function. /// /// # Convergence @@ -143,7 +158,7 @@ pub trait AnalysisDomain<'tcx> { /// monotonically until fixpoint is reached. Note that this monotonicity requirement only applies /// to the same point in the program at different points in time. The dataflow state at a given /// point in the program may or may not be greater than the state at any preceding point. -pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { +pub trait Analysis<'tcx>: AnalysisJoin<'tcx> { /// Updates the current dataflow state with the effect of evaluating a statement. fn apply_statement_effect( &mut self, @@ -238,7 +253,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { &mut self, _block: BasicBlock, _discr: &mir::Operand<'tcx>, - _apply_edge_effects: &mut impl SwitchIntEdgeEffects, + _apply_edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { } @@ -349,18 +364,18 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { } /// See `Analysis::apply_switch_int_edge_effects`. - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, _block: BasicBlock, _discr: &mir::Operand<'tcx>, - _edge_effects: &mut impl SwitchIntEdgeEffects, + _edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { } } impl<'tcx, A> Analysis<'tcx> for A where - A: GenKillAnalysis<'tcx>, + A: GenKillAnalysis<'tcx> + ?Sized, A::Domain: GenKill + BitSetExt, { fn apply_statement_effect( @@ -423,7 +438,7 @@ where &mut self, block: BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, + edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { self.switch_int_edge_effects(block, discr, edge_effects); } @@ -606,10 +621,14 @@ pub struct SwitchIntTarget { } /// A type that records the edge-specific effects for a `SwitchInt` terminator. -pub trait SwitchIntEdgeEffects { +pub trait SwitchIntEdgeEffects<'tcx, A: ?Sized + AnalysisDomain<'tcx>> { /// Calls `apply_edge_effect` for each outgoing edge from a `SwitchInt` terminator and /// records the results. - fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)); + fn apply( + &mut self, + analysis: &mut A, + apply_edge_effect: impl FnMut(&mut A, &mut A::Domain, SwitchIntTarget), + ); } /// List of places that are written to after a successful (non-unwind) return diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 7ddd01e34aaa6..de6a244a6e337 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -376,11 +376,11 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, + edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { return; @@ -395,7 +395,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }; let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|trans, edge| { + edge_effects.apply(self, |self_, trans, edge| { let Some(value) = edge.value else { return; }; @@ -410,9 +410,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // Kill all move paths that correspond to variants we know to be inactive along this // particular outgoing edge of a `SwitchInt`. drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, - self.move_data(), + self_.tcx, + self_.body, + self_.move_data(), enum_place, variant, |mpi| trans.kill(mpi), @@ -492,11 +492,11 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }); } - fn switch_int_edge_effects>( + fn switch_int_edge_effects( &mut self, block: mir::BasicBlock, discr: &mir::Operand<'tcx>, - edge_effects: &mut impl SwitchIntEdgeEffects, + edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration { return; @@ -515,7 +515,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { }; let mut discriminants = enum_def.discriminants(self.tcx); - edge_effects.apply(|trans, edge| { + edge_effects.apply(self, |self_, trans, edge| { let Some(value) = edge.value else { return; }; @@ -530,9 +530,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { // Mark all move paths that correspond to variants other than this one as maybe // uninitialized (in reality, they are *definitely* uninitialized). drop_flag_effects::on_all_inactive_variants( - self.tcx, - self.body, - self.move_data(), + self_.tcx, + self_.body, + self_.move_data(), enum_place, variant, |mpi| trans.gen(mpi), diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 900d438f8d538..ec085090a5ccd 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -27,10 +27,10 @@ pub use self::drop_flag_effects::{ on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, - CallReturnPlaces, CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, - JoinSemiLattice, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, - ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisJoin, AnalysisResults, + Backward, CallReturnPlaces, CloneAnalysis, Direction, Engine, Forward, GenKill, + GenKillAnalysis, JoinSemiLattice, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, + ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 775c522b476f6..32b2eadbdff95 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -17,7 +17,7 @@ use crate::impls::{ use crate::move_paths::{HasMoveData, MoveData}; use crate::move_paths::{LookupResult, MovePathIndex}; use crate::MoveDataParamEnv; -use crate::{Analysis, JoinSemiLattice, ResultsCursor}; +use crate::{Analysis, ResultsCursor}; pub struct SanityCheck; @@ -234,7 +234,7 @@ pub trait RustcPeekAt<'tcx>: Analysis<'tcx> { impl<'tcx, A, D> RustcPeekAt<'tcx> for A where A: Analysis<'tcx, Domain = D> + HasMoveData<'tcx>, - D: JoinSemiLattice + Clone + BitSetExt, + D: Eq + Clone + BitSetExt, { fn peek_at( &self, diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 17bb8fc37ad17..8481161176169 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -47,23 +47,23 @@ use rustc_target::abi::{FieldIdx, VariantIdx}; use crate::lattice::{HasBottom, HasTop}; use crate::{ - fmt::DebugWithContext, Analysis, AnalysisDomain, CallReturnPlaces, JoinSemiLattice, - SwitchIntEdgeEffects, + fmt::DebugWithContext, Analysis, AnalysisDomain, AnalysisJoin, CallReturnPlaces, + JoinSemiLattice, SwitchIntEdgeEffects, }; -pub trait ValueAnalysis<'tcx> { +pub trait ValueAnalysis<'tcx>: Sized { /// For each place of interest, the analysis tracks a value of the given type. - type Value: Clone + JoinSemiLattice + HasBottom + HasTop; + type Value: Clone + Eq + HasBottom + HasTop; const NAME: &'static str; fn map(&self) -> ⤅ - fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State) { + fn handle_statement(&mut self, statement: &Statement<'tcx>, state: &mut State) { self.super_statement(statement, state) } - fn super_statement(&self, statement: &Statement<'tcx>, state: &mut State) { + fn super_statement(&mut self, statement: &Statement<'tcx>, state: &mut State) { match &statement.kind { StatementKind::Assign(box (place, rvalue)) => { self.handle_assign(*place, rvalue, state); @@ -96,7 +96,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_set_discriminant( - &self, + &mut self, place: Place<'tcx>, variant_index: VariantIdx, state: &mut State, @@ -105,7 +105,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_set_discriminant( - &self, + &mut self, place: Place<'tcx>, _variant_index: VariantIdx, state: &mut State, @@ -114,7 +114,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_intrinsic( - &self, + &mut self, intrinsic: &NonDivergingIntrinsic<'tcx>, state: &mut State, ) { @@ -122,7 +122,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_intrinsic( - &self, + &mut self, intrinsic: &NonDivergingIntrinsic<'tcx>, _state: &mut State, ) { @@ -141,7 +141,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_assign( - &self, + &mut self, target: Place<'tcx>, rvalue: &Rvalue<'tcx>, state: &mut State, @@ -150,7 +150,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_assign( - &self, + &mut self, target: Place<'tcx>, rvalue: &Rvalue<'tcx>, state: &mut State, @@ -160,7 +160,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_rvalue( - &self, + &mut self, rvalue: &Rvalue<'tcx>, state: &mut State, ) -> ValueOrPlace { @@ -168,7 +168,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_rvalue( - &self, + &mut self, rvalue: &Rvalue<'tcx>, state: &mut State, ) -> ValueOrPlace { @@ -197,7 +197,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_operand( - &self, + &mut self, operand: &Operand<'tcx>, state: &mut State, ) -> ValueOrPlace { @@ -205,7 +205,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_operand( - &self, + &mut self, operand: &Operand<'tcx>, state: &mut State, ) -> ValueOrPlace { @@ -225,7 +225,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_constant( - &self, + &mut self, constant: &Constant<'tcx>, state: &mut State, ) -> Self::Value { @@ -233,7 +233,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_constant( - &self, + &mut self, _constant: &Constant<'tcx>, _state: &mut State, ) -> Self::Value { @@ -242,11 +242,11 @@ pub trait ValueAnalysis<'tcx> { /// The effect of a successful function call return should not be /// applied here, see [`Analysis::apply_terminator_effect`]. - fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { + fn handle_terminator(&mut self, terminator: &Terminator<'tcx>, state: &mut State) { self.super_terminator(terminator, state) } - fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State) { + fn super_terminator(&mut self, terminator: &Terminator<'tcx>, state: &mut State) { match &terminator.kind { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. @@ -274,7 +274,7 @@ pub trait ValueAnalysis<'tcx> { } fn handle_call_return( - &self, + &mut self, return_places: CallReturnPlaces<'_, 'tcx>, state: &mut State, ) { @@ -282,7 +282,7 @@ pub trait ValueAnalysis<'tcx> { } fn super_call_return( - &self, + &mut self, return_places: CallReturnPlaces<'_, 'tcx>, state: &mut State, ) { @@ -292,24 +292,21 @@ pub trait ValueAnalysis<'tcx> { } fn handle_switch_int( - &self, + self_: &mut ValueAnalysisWrapper, discr: &Operand<'tcx>, - apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + apply_edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, ValueAnalysisWrapper>, ) { - self.super_switch_int(discr, apply_edge_effects) + Self::super_switch_int(self_, discr, apply_edge_effects) } fn super_switch_int( - &self, + _self: &mut ValueAnalysisWrapper, _discr: &Operand<'tcx>, - _apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + _apply_edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, ValueAnalysisWrapper>, ) { } - fn wrap(self) -> ValueAnalysisWrapper - where - Self: Sized, - { + fn wrap(self) -> ValueAnalysisWrapper { ValueAnalysisWrapper(self) } } @@ -341,6 +338,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper impl<'tcx, T> Analysis<'tcx> for ValueAnalysisWrapper where T: ValueAnalysis<'tcx>, + Self: AnalysisJoin<'tcx> + AnalysisDomain<'tcx, Domain = State>, { fn apply_statement_effect( &mut self, @@ -379,10 +377,10 @@ where &mut self, _block: BasicBlock, discr: &Operand<'tcx>, - apply_edge_effects: &mut impl SwitchIntEdgeEffects, + apply_edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, Self>, ) { // FIXME: Dataflow framework provides no access to current state here. - self.0.handle_switch_int(discr, apply_edge_effects) + T::handle_switch_int(self, discr, apply_edge_effects) } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7d7588fcaecd6..db4120b632f33 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -84,7 +84,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } fn handle_set_discriminant( - &self, + &mut self, place: Place<'tcx>, variant_index: VariantIdx, state: &mut State, @@ -103,7 +103,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } fn handle_assign( - &self, + &mut self, target: Place<'tcx>, rvalue: &Rvalue<'tcx>, state: &mut State, @@ -189,7 +189,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } fn handle_rvalue( - &self, + &mut self, rvalue: &Rvalue<'tcx>, state: &mut State, ) -> ValueOrPlace { @@ -237,7 +237,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } fn handle_constant( - &self, + &mut self, constant: &Constant<'tcx>, _state: &mut State, ) -> Self::Value { @@ -250,21 +250,21 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } fn handle_switch_int( - &self, + self_: &mut ValueAnalysisWrapper, discr: &Operand<'tcx>, - apply_edge_effects: &mut impl SwitchIntEdgeEffects>, + apply_edge_effects: &mut impl SwitchIntEdgeEffects<'tcx, ValueAnalysisWrapper>, ) { // FIXME: The dataflow framework only provides the state if we call `apply()`, which makes // this more inefficient than it has to be. let mut discr_value = None; let mut handled = false; - apply_edge_effects.apply(|state, target| { + apply_edge_effects.apply(self_, |self_, state, target| { let discr_value = match discr_value { Some(value) => value, None => { - let value = match self.handle_operand(discr, state) { + let value = match self_.0.handle_operand(discr, state) { ValueOrPlace::Value(value) => value, - ValueOrPlace::Place(place) => state.get_idx(place, self.map()), + ValueOrPlace::Place(place) => state.get_idx(place, self_.0.map()), }; let result = match value { FlatSet::Top => FlatSet::Top, @@ -318,7 +318,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } fn binary_op( - &self, + &mut self, state: &mut State>>, op: BinOp, left: &Operand<'tcx>, @@ -342,7 +342,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } fn eval_operand( - &self, + &mut self, op: &Operand<'tcx>, state: &mut State>>, ) -> FlatSet> {