1
Fork 0

Rename MaybeUnreachable.

This commit is contained in:
Camille GILLOT 2023-05-19 17:41:04 +00:00
parent f19cd3f2e1
commit 6cf15d4cb5
6 changed files with 55 additions and 49 deletions

View file

@ -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)
}
}

View file

@ -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),
}
}
}

View file

@ -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),
}
}
}