diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs index 6a256fae3ca..ac0d2aba39d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -1,6 +1,7 @@ //! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow //! analysis. +use super::lattice::MaybeUnreachable; use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; use rustc_index::Idx; use std::fmt; @@ -124,6 +125,37 @@ where } } +impl DebugWithContext for MaybeUnreachable +where + S: DebugWithContext, +{ + fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + MaybeUnreachable::Unreachable => { + write!(f, "unreachable") + } + MaybeUnreachable::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)) => { + write!(f, "\u{001f}+")?; + set.fmt_with(ctxt, f) + } + (MaybeUnreachable::Reachable(set), MaybeUnreachable::Unreachable) => { + write!(f, "\u{001f}-")?; + set.fmt_with(ctxt, f) + } + (MaybeUnreachable::Reachable(this), MaybeUnreachable::Reachable(old)) => { + this.fmt_diff_with(old, ctxt, f) + } + } + } +} + fn fmt_diff( inserted: &HybridBitSet, removed: &HybridBitSet, diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 2d6a719417f..72ebf5754be 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -272,3 +272,88 @@ impl HasBottom for FlatSet { impl HasTop for FlatSet { const TOP: Self = Self::Top; } + +#[derive(PartialEq, Eq, Debug)] +pub enum MaybeUnreachable { + Unreachable, + Reachable(T), +} + +impl MaybeUnreachable { + pub fn is_reachable(&self) -> bool { + matches!(self, MaybeUnreachable::Reachable(_)) + } +} + +impl HasBottom for MaybeUnreachable { + const BOTTOM: Self = MaybeUnreachable::Unreachable; +} + +impl HasTop for MaybeUnreachable { + const TOP: Self = MaybeUnreachable::Reachable(T::TOP); +} + +impl MaybeUnreachable { + pub fn contains(&self, elem: T) -> bool + where + S: BitSetExt, + { + match self { + MaybeUnreachable::Unreachable => false, + MaybeUnreachable::Reachable(set) => set.contains(elem), + } + } +} + +impl> BitSetExt for MaybeUnreachable { + fn contains(&self, elem: T) -> bool { + self.contains(elem) + } + + fn union(&mut self, other: &HybridBitSet) { + match self { + MaybeUnreachable::Unreachable => {} + MaybeUnreachable::Reachable(set) => set.union(other), + } + } + + fn subtract(&mut self, other: &HybridBitSet) { + match self { + MaybeUnreachable::Unreachable => {} + MaybeUnreachable::Reachable(set) => set.subtract(other), + } + } +} + +impl Clone for MaybeUnreachable { + fn clone(&self) -> Self { + match self { + MaybeUnreachable::Reachable(x) => MaybeUnreachable::Reachable(x.clone()), + MaybeUnreachable::Unreachable => MaybeUnreachable::Unreachable, + } + } + + fn clone_from(&mut self, source: &Self) { + match (&mut *self, source) { + (MaybeUnreachable::Reachable(x), MaybeUnreachable::Reachable(y)) => { + x.clone_from(&y); + } + _ => *self = source.clone(), + } + } +} + +impl JoinSemiLattice for MaybeUnreachable { + fn join(&mut self, other: &Self) -> bool { + match (&mut *self, &other) { + (_, MaybeUnreachable::Unreachable) => false, + (MaybeUnreachable::Unreachable, _) => { + *self = other.clone(); + true + } + (MaybeUnreachable::Reachable(this), MaybeUnreachable::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 8ccd57802d7..b40cf9f4691 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, MeetSemiLattice}; +pub use self::lattice::{JoinSemiLattice, MaybeUnreachable, MeetSemiLattice}; pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor}; /// Analysis domains are all bitsets of various kinds. This trait holds @@ -524,6 +524,22 @@ impl GenKill for ChunkedBitSet { } } +impl> GenKill for MaybeUnreachable { + fn gen(&mut self, elem: T) { + match self { + MaybeUnreachable::Unreachable => {} + MaybeUnreachable::Reachable(set) => set.gen(elem), + } + } + + fn kill(&mut self, elem: T) { + match self { + MaybeUnreachable::Unreachable => {} + MaybeUnreachable::Reachable(set) => set.kill(elem), + } + } +} + impl GenKill for lattice::Dual> { fn gen(&mut self, elem: T) { self.0.insert(elem); diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 900d438f8d5..f627a4867ee 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -29,8 +29,8 @@ pub use self::drop_flag_effects::{ 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, + JoinSemiLattice, MaybeUnreachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, + ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, }; use self::move_paths::MoveData;