1use core::marker::PhantomData;
2
3use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
4
5#[repr(transparent)]
21#[derive(Copy, Clone, Debug, Default, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct Point<T, Provenance> {
24 pub val: T,
26 _token: PhantomData<*mut Provenance>,
27}
28impl<T, Provenance> Point<T, Provenance> {
29 pub fn new(val: T) -> Self {
31 Self {
32 val,
33 _token: PhantomData,
34 }
35 }
36
37 pub fn new_from(val: impl Into<T>) -> Self {
39 Self::new(val.into())
40 }
41}
42impl<T, Provenance> DeepReveal for Point<T, Provenance> {
43 type Revealed = T;
44
45 fn deep_reveal(self) -> Self::Revealed {
46 self.val
47 }
48}
49
50impl<T, Provenance> Merge<Point<T, Provenance>> for Point<T, Provenance>
51where
52 T: PartialEq,
53{
54 fn merge(&mut self, other: Point<T, Provenance>) -> bool {
55 assert!(
56 self.val == other.val,
57 "The `Point` lattice cannot merge inequal elements."
58 );
59 false
60 }
61}
62
63impl<T, Provenance> LatticeFrom<Point<T, Provenance>> for Point<T, Provenance> {
64 fn lattice_from(other: Point<T, Provenance>) -> Self {
65 other
66 }
67}
68
69impl<T, Provenance> PartialOrd<Point<T, Provenance>> for Point<T, Provenance>
70where
71 T: PartialEq,
72{
73 fn partial_cmp(&self, other: &Point<T, Provenance>) -> Option<core::cmp::Ordering> {
74 assert!(
75 self.val == other.val,
76 "The `Point` lattice does not have a partial order between inequal elements."
77 );
78 Some(core::cmp::Ordering::Equal)
79 }
80}
81impl<T, Provenance> LatticeOrd<Point<T, Provenance>> for Point<T, Provenance> where
82 Self: PartialOrd<Point<T, Provenance>>
83{
84}
85
86impl<T, Provenance> PartialEq<Point<T, Provenance>> for Point<T, Provenance>
87where
88 T: PartialEq,
89{
90 fn eq(&self, other: &Point<T, Provenance>) -> bool {
91 self.val == other.val
92 }
93}
94
95impl<T, Provenance> IsBot for Point<T, Provenance> {
96 fn is_bot(&self) -> bool {
97 true
98 }
99}
100
101impl<T, Provenance> IsTop for Point<T, Provenance> {
102 fn is_top(&self) -> bool {
103 true
104 }
105}
106
107#[cfg(test)]
108mod test {
109 use super::*;
110 use crate::test::{
111 check_all, check_lattice_ord, check_lattice_properties, check_partial_ord_properties,
112 };
113
114 #[test]
115 fn consistency_equal() {
116 check_all(&[Point::<_, ()>::new("hello world")])
117 }
118
119 #[test]
120 fn consistency_inequal() {
121 use std::collections::BTreeSet;
122
123 let items: &[Point<_, ()>] = &[
124 Point::new(BTreeSet::from_iter([])),
125 Point::new(BTreeSet::from_iter([0])),
126 Point::new(BTreeSet::from_iter([1])),
127 Point::new(BTreeSet::from_iter([0, 1])),
128 ];
129
130 assert!(std::panic::catch_unwind(|| check_lattice_ord(items)).is_err());
132 assert!(std::panic::catch_unwind(|| check_partial_ord_properties(items)).is_err());
134 assert!(std::panic::catch_unwind(|| check_lattice_properties(items)).is_err());
136 }
137}