Rename MaybeUnreachable.
This commit is contained in:
parent
f19cd3f2e1
commit
6cf15d4cb5
6 changed files with 55 additions and 49 deletions
|
@ -1,7 +1,7 @@
|
||||||
//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
|
//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
|
||||||
//! analysis.
|
//! analysis.
|
||||||
|
|
||||||
use super::lattice::MaybeUnreachable;
|
use super::lattice::MaybeReachable;
|
||||||
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
|
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
use std::fmt;
|
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
|
where
|
||||||
S: DebugWithContext<C>,
|
S: DebugWithContext<C>,
|
||||||
{
|
{
|
||||||
fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => {
|
MaybeReachable::Unreachable => {
|
||||||
write!(f, "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 {
|
fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match (self, old) {
|
match (self, old) {
|
||||||
(MaybeUnreachable::Unreachable, MaybeUnreachable::Unreachable) => Ok(()),
|
(MaybeReachable::Unreachable, MaybeReachable::Unreachable) => Ok(()),
|
||||||
(MaybeUnreachable::Unreachable, MaybeUnreachable::Reachable(set)) => {
|
(MaybeReachable::Unreachable, MaybeReachable::Reachable(set)) => {
|
||||||
write!(f, "\u{001f}+")?;
|
write!(f, "\u{001f}+")?;
|
||||||
set.fmt_with(ctxt, f)
|
set.fmt_with(ctxt, f)
|
||||||
}
|
}
|
||||||
(MaybeUnreachable::Reachable(set), MaybeUnreachable::Unreachable) => {
|
(MaybeReachable::Reachable(set), MaybeReachable::Unreachable) => {
|
||||||
write!(f, "\u{001f}-")?;
|
write!(f, "\u{001f}-")?;
|
||||||
set.fmt_with(ctxt, f)
|
set.fmt_with(ctxt, f)
|
||||||
}
|
}
|
||||||
(MaybeUnreachable::Reachable(this), MaybeUnreachable::Reachable(old)) => {
|
(MaybeReachable::Reachable(this), MaybeReachable::Reachable(old)) => {
|
||||||
this.fmt_diff_with(old, ctxt, f)
|
this.fmt_diff_with(old, ctxt, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,69 +273,75 @@ impl<T> HasTop for FlatSet<T> {
|
||||||
const TOP: Self = Self::Top;
|
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)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum MaybeUnreachable<T> {
|
pub enum MaybeReachable<T> {
|
||||||
Unreachable,
|
Unreachable,
|
||||||
Reachable(T),
|
Reachable(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> MaybeUnreachable<T> {
|
impl<T> MaybeReachable<T> {
|
||||||
pub fn is_reachable(&self) -> bool {
|
pub fn is_reachable(&self) -> bool {
|
||||||
matches!(self, MaybeUnreachable::Reachable(_))
|
matches!(self, MaybeReachable::Reachable(_))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> HasBottom for MaybeUnreachable<T> {
|
impl<T> HasBottom for MaybeReachable<T> {
|
||||||
const BOTTOM: Self = MaybeUnreachable::Unreachable;
|
const BOTTOM: Self = MaybeReachable::Unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasTop> HasTop for MaybeUnreachable<T> {
|
impl<T: HasTop> HasTop for MaybeReachable<T> {
|
||||||
const TOP: Self = MaybeUnreachable::Reachable(T::TOP);
|
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
|
pub fn contains<T>(&self, elem: T) -> bool
|
||||||
where
|
where
|
||||||
S: BitSetExt<T>,
|
S: BitSetExt<T>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => false,
|
MaybeReachable::Unreachable => false,
|
||||||
MaybeUnreachable::Reachable(set) => set.contains(elem),
|
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 {
|
fn contains(&self, elem: T) -> bool {
|
||||||
self.contains(elem)
|
self.contains(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn union(&mut self, other: &HybridBitSet<T>) {
|
fn union(&mut self, other: &HybridBitSet<T>) {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => {}
|
MaybeReachable::Unreachable => {}
|
||||||
MaybeUnreachable::Reachable(set) => set.union(other),
|
MaybeReachable::Reachable(set) => set.union(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtract(&mut self, other: &HybridBitSet<T>) {
|
fn subtract(&mut self, other: &HybridBitSet<T>) {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => {}
|
MaybeReachable::Unreachable => {}
|
||||||
MaybeUnreachable::Reachable(set) => set.subtract(other),
|
MaybeReachable::Reachable(set) => set.subtract(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Clone> Clone for MaybeUnreachable<V> {
|
impl<V: Clone> Clone for MaybeReachable<V> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Reachable(x) => MaybeUnreachable::Reachable(x.clone()),
|
MaybeReachable::Reachable(x) => MaybeReachable::Reachable(x.clone()),
|
||||||
MaybeUnreachable::Unreachable => MaybeUnreachable::Unreachable,
|
MaybeReachable::Unreachable => MaybeReachable::Unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_from(&mut self, source: &Self) {
|
fn clone_from(&mut self, source: &Self) {
|
||||||
match (&mut *self, source) {
|
match (&mut *self, source) {
|
||||||
(MaybeUnreachable::Reachable(x), MaybeUnreachable::Reachable(y)) => {
|
(MaybeReachable::Reachable(x), MaybeReachable::Reachable(y)) => {
|
||||||
x.clone_from(&y);
|
x.clone_from(&y);
|
||||||
}
|
}
|
||||||
_ => *self = source.clone(),
|
_ => *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 {
|
fn join(&mut self, other: &Self) -> bool {
|
||||||
|
// Unreachable acts as a bottom.
|
||||||
match (&mut *self, &other) {
|
match (&mut *self, &other) {
|
||||||
(_, MaybeUnreachable::Unreachable) => false,
|
(_, MaybeReachable::Unreachable) => false,
|
||||||
(MaybeUnreachable::Unreachable, _) => {
|
(MaybeReachable::Unreachable, _) => {
|
||||||
*self = other.clone();
|
*self = other.clone();
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(MaybeUnreachable::Reachable(this), MaybeUnreachable::Reachable(other)) => {
|
(MaybeReachable::Reachable(this), MaybeReachable::Reachable(other)) => this.join(other),
|
||||||
this.join(other)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ mod visitor;
|
||||||
pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
|
pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
|
||||||
pub use self::direction::{Backward, Direction, Forward};
|
pub use self::direction::{Backward, Direction, Forward};
|
||||||
pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
|
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};
|
pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
|
||||||
|
|
||||||
/// Analysis domains are all bitsets of various kinds. This trait holds
|
/// 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) {
|
fn gen(&mut self, elem: T) {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => {}
|
// If the state is not reachable, adding an element does nothing.
|
||||||
MaybeUnreachable::Reachable(set) => set.gen(elem),
|
MaybeReachable::Unreachable => {}
|
||||||
|
MaybeReachable::Reachable(set) => set.gen(elem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill(&mut self, elem: T) {
|
fn kill(&mut self, elem: T) {
|
||||||
match self {
|
match self {
|
||||||
MaybeUnreachable::Unreachable => {}
|
// If the state is not reachable, killing an element does nothing.
|
||||||
MaybeUnreachable::Reachable(set) => set.kill(elem),
|
MaybeReachable::Unreachable => {}
|
||||||
|
MaybeReachable::Reachable(set) => set.kill(elem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData
|
||||||
use crate::on_lookup_result_bits;
|
use crate::on_lookup_result_bits;
|
||||||
use crate::MoveDataParamEnv;
|
use crate::MoveDataParamEnv;
|
||||||
use crate::{drop_flag_effects, on_all_children_bits, on_all_drop_children_bits};
|
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
|
/// `MaybeInitializedPlaces` tracks all places that might be
|
||||||
/// initialized upon reaching a particular point in the control flow
|
/// 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(
|
pub fn is_unwind_dead(
|
||||||
&self,
|
&self,
|
||||||
place: mir::Place<'tcx>,
|
place: mir::Place<'tcx>,
|
||||||
state: &MaybeUnreachable<ChunkedBitSet<MovePathIndex>>,
|
state: &MaybeReachable<ChunkedBitSet<MovePathIndex>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
|
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
|
||||||
let mut maybe_live = false;
|
let mut maybe_live = false;
|
||||||
|
@ -308,18 +308,17 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||||
type Domain = MaybeUnreachable<ChunkedBitSet<MovePathIndex>>;
|
type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
|
||||||
const NAME: &'static str = "maybe_init";
|
const NAME: &'static str = "maybe_init";
|
||||||
|
|
||||||
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
|
fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
|
||||||
// bottom = uninitialized
|
// bottom = uninitialized
|
||||||
MaybeUnreachable::Unreachable
|
MaybeReachable::Unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
||||||
*state = MaybeUnreachable::Reachable(ChunkedBitSet::new_empty(
|
*state =
|
||||||
self.move_data().move_paths.len(),
|
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| {
|
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||||
assert!(s == DropFlagState::Present);
|
assert!(s == DropFlagState::Present);
|
||||||
state.gen(path);
|
state.gen(path);
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub use self::drop_flag_effects::{
|
||||||
pub use self::framework::{
|
pub use self::framework::{
|
||||||
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward,
|
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward,
|
||||||
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
|
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
|
||||||
MaybeUnreachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
|
MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
|
||||||
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
|
||||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||||
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
||||||
use rustc_mir_dataflow::{
|
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;
|
use rustc_target::abi::FieldIdx;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
|
||||||
let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
|
let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
|
||||||
|
|
||||||
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
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.
|
// 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 {
|
let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue