diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs index ac0d2aba39d..e3a66bd952c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -1,7 +1,7 @@ //! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow //! analysis. -use super::lattice::MaybeUnreachable; +use super::lattice::MaybeReachable; use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; use rustc_index::Idx; use std::fmt; @@ -125,31 +125,31 @@ where } } -impl<S, C> DebugWithContext<C> for MaybeUnreachable<S> +impl<S, C> DebugWithContext<C> for MaybeReachable<S> where S: DebugWithContext<C>, { fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - MaybeUnreachable::Unreachable => { + MaybeReachable::Unreachable => { write!(f, "unreachable") } - MaybeUnreachable::Reachable(set) => set.fmt_with(ctxt, f), + MaybeReachable::Reachable(set) => set.fmt_with(ctxt, f), } } fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { match (self, old) { - (MaybeUnreachable::Unreachable, MaybeUnreachable::Unreachable) => Ok(()), - (MaybeUnreachable::Unreachable, MaybeUnreachable::Reachable(set)) => { + (MaybeReachable::Unreachable, MaybeReachable::Unreachable) => Ok(()), + (MaybeReachable::Unreachable, MaybeReachable::Reachable(set)) => { write!(f, "\u{001f}+")?; set.fmt_with(ctxt, f) } - (MaybeUnreachable::Reachable(set), MaybeUnreachable::Unreachable) => { + (MaybeReachable::Reachable(set), MaybeReachable::Unreachable) => { write!(f, "\u{001f}-")?; set.fmt_with(ctxt, f) } - (MaybeUnreachable::Reachable(this), MaybeUnreachable::Reachable(old)) => { + (MaybeReachable::Reachable(this), MaybeReachable::Reachable(old)) => { this.fmt_diff_with(old, ctxt, f) } } diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 72ebf5754be..3b89598d289 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -273,69 +273,75 @@ impl<T> HasTop for FlatSet<T> { const TOP: Self = Self::Top; } +/// Extend a lattice with a bottom value to represent an unreachable execution. +/// +/// The only useful action on an unreachable state is joining it with a reachable one to make it +/// reachable. All other actions, gen/kill for instance, are no-ops. #[derive(PartialEq, Eq, Debug)] -pub enum MaybeUnreachable<T> { +pub enum MaybeReachable<T> { Unreachable, Reachable(T), } -impl<T> MaybeUnreachable<T> { +impl<T> MaybeReachable<T> { pub fn is_reachable(&self) -> bool { - matches!(self, MaybeUnreachable::Reachable(_)) + matches!(self, MaybeReachable::Reachable(_)) } } -impl<T> HasBottom for MaybeUnreachable<T> { - const BOTTOM: Self = MaybeUnreachable::Unreachable; +impl<T> HasBottom for MaybeReachable<T> { + const BOTTOM: Self = MaybeReachable::Unreachable; } -impl<T: HasTop> HasTop for MaybeUnreachable<T> { - const TOP: Self = MaybeUnreachable::Reachable(T::TOP); +impl<T: HasTop> HasTop for MaybeReachable<T> { + const TOP: Self = MaybeReachable::Reachable(T::TOP); } -impl<S> MaybeUnreachable<S> { +impl<S> MaybeReachable<S> { + /// Return whether the current state contains the given element. If the state is unreachable, + /// it does no contain anything. pub fn contains<T>(&self, elem: T) -> bool where S: BitSetExt<T>, { match self { - MaybeUnreachable::Unreachable => false, - MaybeUnreachable::Reachable(set) => set.contains(elem), + MaybeReachable::Unreachable => false, + MaybeReachable::Reachable(set) => set.contains(elem), } } } -impl<T, S: BitSetExt<T>> BitSetExt<T> for MaybeUnreachable<S> { +impl<T, S: BitSetExt<T>> BitSetExt<T> for MaybeReachable<S> { fn contains(&self, elem: T) -> bool { self.contains(elem) } fn union(&mut self, other: &HybridBitSet<T>) { match self { - MaybeUnreachable::Unreachable => {} - MaybeUnreachable::Reachable(set) => set.union(other), + MaybeReachable::Unreachable => {} + MaybeReachable::Reachable(set) => set.union(other), } } fn subtract(&mut self, other: &HybridBitSet<T>) { match self { - MaybeUnreachable::Unreachable => {} - MaybeUnreachable::Reachable(set) => set.subtract(other), + MaybeReachable::Unreachable => {} + MaybeReachable::Reachable(set) => set.subtract(other), } } } -impl<V: Clone> Clone for MaybeUnreachable<V> { +impl<V: Clone> Clone for MaybeReachable<V> { fn clone(&self) -> Self { match self { - MaybeUnreachable::Reachable(x) => MaybeUnreachable::Reachable(x.clone()), - MaybeUnreachable::Unreachable => MaybeUnreachable::Unreachable, + MaybeReachable::Reachable(x) => MaybeReachable::Reachable(x.clone()), + MaybeReachable::Unreachable => MaybeReachable::Unreachable, } } fn clone_from(&mut self, source: &Self) { match (&mut *self, source) { - (MaybeUnreachable::Reachable(x), MaybeUnreachable::Reachable(y)) => { + (MaybeReachable::Reachable(x), MaybeReachable::Reachable(y)) => { x.clone_from(&y); } _ => *self = source.clone(), @@ -343,17 +349,16 @@ impl<V: Clone> Clone for MaybeUnreachable<V> { } } -impl<T: JoinSemiLattice + Clone> JoinSemiLattice for MaybeUnreachable<T> { +impl<T: JoinSemiLattice + Clone> JoinSemiLattice for MaybeReachable<T> { fn join(&mut self, other: &Self) -> bool { + // Unreachable acts as a bottom. match (&mut *self, &other) { - (_, MaybeUnreachable::Unreachable) => false, - (MaybeUnreachable::Unreachable, _) => { + (_, MaybeReachable::Unreachable) => false, + (MaybeReachable::Unreachable, _) => { *self = other.clone(); true } - (MaybeUnreachable::Reachable(this), MaybeUnreachable::Reachable(other)) => { - this.join(other) - } + (MaybeReachable::Reachable(this), MaybeReachable::Reachable(other)) => this.join(other), } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 4d915997791..9fe8b509c56 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -48,7 +48,7 @@ mod visitor; pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor}; pub use self::direction::{Backward, Direction, Forward}; pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; -pub use self::lattice::{JoinSemiLattice, MaybeUnreachable, MeetSemiLattice}; +pub use self::lattice::{JoinSemiLattice, MaybeReachable, MeetSemiLattice}; pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor}; /// Analysis domains are all bitsets of various kinds. This trait holds @@ -492,18 +492,20 @@ impl<T: Idx> GenKill<T> for ChunkedBitSet<T> { } } -impl<T, S: GenKill<T>> GenKill<T> for MaybeUnreachable<S> { +impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> { fn gen(&mut self, elem: T) { match self { - MaybeUnreachable::Unreachable => {} - MaybeUnreachable::Reachable(set) => set.gen(elem), + // If the state is not reachable, adding an element does nothing. + MaybeReachable::Unreachable => {} + MaybeReachable::Reachable(set) => set.gen(elem), } } fn kill(&mut self, elem: T) { match self { - MaybeUnreachable::Unreachable => {} - MaybeUnreachable::Reachable(set) => set.kill(elem), + // If the state is not reachable, killing an element does nothing. + MaybeReachable::Unreachable => {} + MaybeReachable::Reachable(set) => set.kill(elem), } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index ebae25146de..20d4ba7b51c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -11,7 +11,7 @@ use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData use crate::on_lookup_result_bits; use crate::MoveDataParamEnv; use crate::{drop_flag_effects, on_all_children_bits, on_all_drop_children_bits}; -use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeUnreachable}; +use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeReachable}; /// `MaybeInitializedPlaces` tracks all places that might be /// initialized upon reaching a particular point in the control flow @@ -68,7 +68,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { pub fn is_unwind_dead( &self, place: mir::Place<'tcx>, - state: &MaybeUnreachable<ChunkedBitSet<MovePathIndex>>, + state: &MaybeReachable<ChunkedBitSet<MovePathIndex>>, ) -> bool { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { let mut maybe_live = false; @@ -308,18 +308,17 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { } impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { - type Domain = MaybeUnreachable<ChunkedBitSet<MovePathIndex>>; + type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>; const NAME: &'static str = "maybe_init"; fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { // bottom = uninitialized - MaybeUnreachable::Unreachable + MaybeReachable::Unreachable } fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { - *state = MaybeUnreachable::Reachable(ChunkedBitSet::new_empty( - self.move_data().move_paths.len(), - )); + *state = + MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| { assert!(s == DropFlagState::Present); state.gen(path); diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 0ec84d2789d..0cdbee19d2c 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -29,7 +29,7 @@ pub use self::drop_flag_effects::{ pub use self::framework::{ fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, - MaybeUnreachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, + MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, }; diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index e89f719d7c9..26384974798 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{ - self, move_path_children_matching, Analysis, MaybeUnreachable, MoveDataParamEnv, + self, move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv, }; use rustc_target::abi::FieldIdx; @@ -43,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue }; maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); - let MaybeUnreachable::Reachable(maybe_inits) = maybe_inits.get() else { continue }; + let MaybeReachable::Reachable(maybe_inits) = maybe_inits.get() else { continue }; // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone. let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {