about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/fmt.rs32
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs85
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs18
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs4
4 files changed, 136 insertions, 3 deletions
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<S, C> DebugWithContext<C> for MaybeUnreachable<S>
+where
+    S: DebugWithContext<C>,
+{
+    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<T, C>(
     inserted: &HybridBitSet<T>,
     removed: &HybridBitSet<T>,
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<T> HasBottom for FlatSet<T> {
 impl<T> HasTop for FlatSet<T> {
     const TOP: Self = Self::Top;
 }
+
+#[derive(PartialEq, Eq, Debug)]
+pub enum MaybeUnreachable<T> {
+    Unreachable,
+    Reachable(T),
+}
+
+impl<T> MaybeUnreachable<T> {
+    pub fn is_reachable(&self) -> bool {
+        matches!(self, MaybeUnreachable::Reachable(_))
+    }
+}
+
+impl<T> HasBottom for MaybeUnreachable<T> {
+    const BOTTOM: Self = MaybeUnreachable::Unreachable;
+}
+
+impl<T: HasTop> HasTop for MaybeUnreachable<T> {
+    const TOP: Self = MaybeUnreachable::Reachable(T::TOP);
+}
+
+impl<S> MaybeUnreachable<S> {
+    pub fn contains<T>(&self, elem: T) -> bool
+    where
+        S: BitSetExt<T>,
+    {
+        match self {
+            MaybeUnreachable::Unreachable => false,
+            MaybeUnreachable::Reachable(set) => set.contains(elem),
+        }
+    }
+}
+
+impl<T, S: BitSetExt<T>> BitSetExt<T> for MaybeUnreachable<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),
+        }
+    }
+
+    fn subtract(&mut self, other: &HybridBitSet<T>) {
+        match self {
+            MaybeUnreachable::Unreachable => {}
+            MaybeUnreachable::Reachable(set) => set.subtract(other),
+        }
+    }
+}
+
+impl<V: Clone> Clone for MaybeUnreachable<V> {
+    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<T: JoinSemiLattice + Clone> JoinSemiLattice for MaybeUnreachable<T> {
+    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<T: Idx> GenKill<T> for ChunkedBitSet<T> {
     }
 }
 
+impl<T, S: GenKill<T>> GenKill<T> for MaybeUnreachable<S> {
+    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<T: Idx> GenKill<T> for lattice::Dual<BitSet<T>> {
     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;