Make HasTop and HasBottom consts.

This commit is contained in:
Camille GILLOT 2023-04-24 17:10:39 +00:00
parent f7b831ac8a
commit 71138e9933
3 changed files with 24 additions and 34 deletions

View File

@ -75,12 +75,12 @@ pub trait MeetSemiLattice: Eq {
/// A set that has a "bottom" element, which is less than or equal to any other element.
pub trait HasBottom {
fn bottom() -> Self;
const BOTTOM: Self;
}
/// A set that has a "top" element, which is greater than or equal to any other element.
pub trait HasTop {
fn top() -> Self;
const TOP: Self;
}
/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom:
@ -113,15 +113,11 @@ fn meet(&mut self, other: &Self) -> bool {
}
impl HasBottom for bool {
fn bottom() -> Self {
false
}
const BOTTOM: Self = false;
}
impl HasTop for bool {
fn top() -> Self {
true
}
const TOP: Self = true;
}
/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation
@ -274,13 +270,9 @@ fn meet(&mut self, other: &Self) -> bool {
}
impl<T> HasBottom for FlatSet<T> {
fn bottom() -> Self {
Self::Bottom
}
const BOTTOM: Self = Self::Bottom;
}
impl<T> HasTop for FlatSet<T> {
fn top() -> Self {
Self::Top
}
const TOP: Self = Self::Top;
}

View File

@ -74,11 +74,11 @@ fn super_statement(&self, statement: &Statement<'tcx>, state: &mut State<Self::V
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
// StorageLive leaves the local in an uninitialized state.
// StorageDead makes it UB to access the local afterwards.
state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::bottom());
state.flood_with(Place::from(*local).as_ref(), self.map(), Self::Value::BOTTOM);
}
StatementKind::Deinit(box place) => {
// Deinit makes the place uninitialized.
state.flood_with(place.as_ref(), self.map(), Self::Value::bottom());
state.flood_with(place.as_ref(), self.map(), Self::Value::BOTTOM);
}
StatementKind::Retag(..) => {
// We don't track references.
@ -154,7 +154,7 @@ fn super_rvalue(
Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state),
Rvalue::Ref(..) | Rvalue::AddressOf(..) => {
// We don't track such places.
ValueOrPlace::top()
ValueOrPlace::TOP
}
Rvalue::Repeat(..)
| Rvalue::ThreadLocalRef(..)
@ -168,7 +168,7 @@ fn super_rvalue(
| Rvalue::Aggregate(..)
| Rvalue::ShallowInitBox(..) => {
// No modification is possible through these r-values.
ValueOrPlace::top()
ValueOrPlace::TOP
}
}
}
@ -196,7 +196,7 @@ fn super_operand(
self.map()
.find(place.as_ref())
.map(ValueOrPlace::Place)
.unwrap_or(ValueOrPlace::top())
.unwrap_or(ValueOrPlace::TOP)
}
}
}
@ -214,7 +214,7 @@ fn super_constant(
_constant: &Constant<'tcx>,
_state: &mut State<Self::Value>,
) -> Self::Value {
Self::Value::top()
Self::Value::TOP
}
/// The effect of a successful function call return should not be
@ -229,7 +229,7 @@ fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self
// Effect is applied by `handle_call_return`.
}
TerminatorKind::Drop { place, .. } => {
state.flood_with(place.as_ref(), self.map(), Self::Value::bottom());
state.flood_with(place.as_ref(), self.map(), Self::Value::BOTTOM);
}
TerminatorKind::Yield { .. } => {
// They would have an effect, but are not allowed in this phase.
@ -307,7 +307,7 @@ fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
// The initial state maps all tracked places of argument projections to and the rest to ⊥.
assert!(matches!(state.0, StateData::Unreachable));
let values = IndexVec::from_elem_n(T::Value::bottom(), self.0.map().value_count);
let values = IndexVec::from_elem_n(T::Value::BOTTOM, self.0.map().value_count);
*state = State(StateData::Reachable(values));
for arg in body.args_iter() {
state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map());
@ -437,7 +437,7 @@ pub fn mark_unreachable(&mut self) {
}
pub fn flood_all(&mut self) {
self.flood_all_with(V::top())
self.flood_all_with(V::TOP)
}
pub fn flood_all_with(&mut self, value: V) {
@ -455,7 +455,7 @@ pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
}
pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map) {
self.flood_with(place, map, V::top())
self.flood_with(place, map, V::TOP)
}
pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
@ -468,7 +468,7 @@ pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
}
pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map) {
self.flood_discr_with(place, map, V::top())
self.flood_discr_with(place, map, V::TOP)
}
/// Low-level method that assigns to a place.
@ -538,14 +538,14 @@ pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, ma
/// Retrieve the value stored for a place, or if it is not tracked.
pub fn get(&self, place: PlaceRef<'_>, map: &Map) -> V {
map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::top())
map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::TOP)
}
/// Retrieve the value stored for a place, or if it is not tracked.
pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V {
match map.find_discr(place) {
Some(place) => self.get_idx(place, map),
None => V::top(),
None => V::TOP,
}
}
@ -553,11 +553,11 @@ pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V {
pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V {
match &self.0 {
StateData::Reachable(values) => {
map.places[place].value_index.map(|v| values[v].clone()).unwrap_or(V::top())
map.places[place].value_index.map(|v| values[v].clone()).unwrap_or(V::TOP)
}
StateData::Unreachable => {
// Because this is unreachable, we can return any value we want.
V::bottom()
V::BOTTOM
}
}
}
@ -909,9 +909,7 @@ pub enum ValueOrPlace<V> {
}
impl<V: HasTop> ValueOrPlace<V> {
pub fn top() -> Self {
ValueOrPlace::Value(V::top())
}
pub const TOP: Self = ValueOrPlace::Value(V::TOP);
}
/// The set of projection elements that can be used by a tracked place.

View File

@ -208,8 +208,8 @@ fn handle_rvalue(
_ => unreachable!(),
}
.map(|result| ValueOrPlace::Value(self.wrap_immediate(result, *ty)))
.unwrap_or(ValueOrPlace::top()),
_ => ValueOrPlace::top(),
.unwrap_or(ValueOrPlace::TOP),
_ => ValueOrPlace::TOP,
},
Rvalue::BinaryOp(op, box (left, right)) => {
// Overflows must be ignored here.