Skip to content

Commit e178a87

Browse files
Expand documentation for the lattice module
1 parent c03eba2 commit e178a87

File tree

1 file changed

+51
-17
lines changed
  • compiler/rustc_mir/src/dataflow/framework

1 file changed

+51
-17
lines changed

compiler/rustc_mir/src/dataflow/framework/lattice.rs

+51-17
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,42 @@
11
//! Traits used to represent [lattices] for use as the domain of a dataflow analysis.
22
//!
3-
//! ## Implementation Notes
3+
//! # Overview
44
//!
5-
//! Given that they represent partially ordered sets, you may be surprised that [`MeetSemiLattice`]
6-
//! and [`JoinSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This
7-
//! is because most standard library types use lexicographic ordering instead of [set inclusion]
8-
//! for their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a
9-
//! dataflow analysis, there's no need for a hypothetical `SetInclusion` newtype with a custom
10-
//! `PartialOrd` impl. The only benefit would be the ability to check (in debug mode) that the
11-
//! least upper (or greatest lower) bound returned by the lattice join (or meet) operator was in
12-
//! fact greater (or lower) than the inputs.
5+
//! The most common lattice is a powerset of some set `S`, ordered by [set inclusion]. The [Hasse
6+
//! diagram] for the powerset of a set with two elements (`X` and `Y`) is shown below. Note that
7+
//! distinct elements at the same height in a Hasse diagram (e.g. `{X}` and `{Y}`) are
8+
//! *incomparable*, not equal.
9+
//!
10+
//! ```text
11+
//! {X, Y} <- top
12+
//! / \
13+
//! {X} {Y}
14+
//! \ /
15+
//! {} <- bottom
16+
//!
17+
//! ```
18+
//!
19+
//! The defining characteristic of a lattice—the one that differentiates it from a [partially
20+
//! ordered set][poset]—is the existence of a *unique* least upper and greatest lower bound for
21+
//! every pair of elements. The lattice join operator (`∨`) returns the least upper bound, and the
22+
//! lattice meet operator (`∧`) returns the greatest lower bound. Types that implement one operator
23+
//! but not the other are known as semilattices. Dataflow analysis only uses the join operator and
24+
//! will work with any join-semilattice, but both should be specified when possible.
25+
//!
26+
//! ## `PartialOrd`
27+
//!
28+
//! Given that they represent partially ordered sets, you may be surprised that [`JoinSemiLattice`]
29+
//! and [`MeetSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This
30+
//! is because most standard library types use lexicographic ordering instead of set inclusion for
31+
//! their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a
32+
//! dataflow analysis, there's no need for a newtype wrapper with a custom `PartialOrd` impl. The
33+
//! only benefit would be the ability to check that the least upper (or greatest lower) bound
34+
//! returned by the lattice join (or meet) operator was in fact greater (or lower) than the inputs.
1335
//!
1436
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
1537
//! [set inclusion]: https://en.wikipedia.org/wiki/Subset
38+
//! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
39+
//! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
1640
1741
use rustc_index::bit_set::BitSet;
1842
use rustc_index::vec::{Idx, IndexVec};
@@ -47,7 +71,13 @@ pub trait MeetSemiLattice: Eq {
4771
fn meet(&mut self, other: &Self) -> bool;
4872
}
4973

50-
/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom.
74+
/// A `bool` is a "two-point" lattice with `true` as the top element and `false` as the bottom:
75+
///
76+
/// ```text
77+
/// true
78+
/// |
79+
/// false
80+
/// ```
5181
impl JoinSemiLattice for bool {
5282
fn join(&mut self, other: &Self) -> bool {
5383
if let (false, true) = (*self, *other) {
@@ -70,8 +100,11 @@ impl MeetSemiLattice for bool {
70100
}
71101
}
72102

73-
/// A tuple or list of lattices is itself a lattice whose least upper bound is the concatenation of
74-
/// the least upper bounds of each element of the tuple or list.
103+
/// A tuple (or list) of lattices is itself a lattice whose least upper bound is the concatenation
104+
/// of the least upper bounds of each element of the tuple (or list).
105+
///
106+
/// In other words:
107+
/// (A₀, A₁, ..., Aₙ) ∨ (B₀, B₁, ..., Bₙ) = (A₀∨B₀, A₁∨B₁, ..., Aₙ∨Bₙ)
75108
impl<I: Idx, T: JoinSemiLattice> JoinSemiLattice for IndexVec<I, T> {
76109
fn join(&mut self, other: &Self) -> bool {
77110
assert_eq!(self.len(), other.len());
@@ -96,9 +129,9 @@ impl<I: Idx, T: MeetSemiLattice> MeetSemiLattice for IndexVec<I, T> {
96129
}
97130
}
98131

99-
/// A `BitSet` is an efficent way to store a tuple of "two-point" lattices. Equivalently, it is the
100-
/// lattice corresponding to the powerset of the set of all possibe values of the index type `T`
101-
/// ordered by inclusion.
132+
/// A `BitSet` represents the lattice formed by the powerset of all possible values of
133+
/// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices,
134+
/// one for each possible value of `T`.
102135
impl<T: Idx> JoinSemiLattice for BitSet<T> {
103136
fn join(&mut self, other: &Self) -> bool {
104137
self.union(other)
@@ -146,8 +179,7 @@ impl<T: JoinSemiLattice> MeetSemiLattice for Dual<T> {
146179
}
147180

148181
/// Extends a type `T` with top and bottom elements to make it a partially ordered set in which no
149-
/// value of `T` is comparable with any other. A flat set has the following [Hasse
150-
/// diagram](https://en.wikipedia.org/wiki/Hasse_diagram):
182+
/// value of `T` is comparable with any other. A flat set has the following [Hasse diagram]:
151183
///
152184
/// ```text
153185
/// top
@@ -156,6 +188,8 @@ impl<T: JoinSemiLattice> MeetSemiLattice for Dual<T> {
156188
/// \ \ / /
157189
/// bottom
158190
/// ```
191+
///
192+
/// [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
159193
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
160194
pub enum FlatSet<T> {
161195
Bottom,

0 commit comments

Comments
 (0)