1use std::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 if self.val != other.val {
56 panic!("The `Point` lattice cannot merge inequal elements.")
57 }
58 false
59 }
60}
61
62impl<T, Provenance> LatticeFrom<Point<T, Provenance>> for Point<T, Provenance> {
63 fn lattice_from(other: Point<T, Provenance>) -> Self {
64 other
65 }
66}
67
68impl<T, Provenance> PartialOrd<Point<T, Provenance>> for Point<T, Provenance>
69where
70 T: PartialEq,
71{
72 fn partial_cmp(&self, other: &Point<T, Provenance>) -> Option<std::cmp::Ordering> {
73 if self.val != other.val {
74 panic!("The `Point` lattice does not have a partial order between inequal elements.");
75 }
76 Some(std::cmp::Ordering::Equal)
77 }
78}
79impl<T, Provenance> LatticeOrd<Point<T, Provenance>> for Point<T, Provenance> where
80 Self: PartialOrd<Point<T, Provenance>>
81{
82}
83
84impl<T, Provenance> PartialEq<Point<T, Provenance>> for Point<T, Provenance>
85where
86 T: PartialEq,
87{
88 fn eq(&self, other: &Point<T, Provenance>) -> bool {
89 self.val == other.val
90 }
91}
92
93impl<T, Provenance> IsBot for Point<T, Provenance> {
94 fn is_bot(&self) -> bool {
95 true
96 }
97}
98
99impl<T, Provenance> IsTop for Point<T, Provenance> {
100 fn is_top(&self) -> bool {
101 true
102 }
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108 use crate::test::{
109 check_all, check_lattice_ord, check_lattice_properties, check_partial_ord_properties,
110 };
111
112 #[test]
113 fn consistency_equal() {
114 check_all(&[Point::<_, ()>::new("hello world")])
115 }
116
117 #[test]
118 fn consistency_inequal() {
119 use std::collections::BTreeSet;
120
121 let items: &[Point<_, ()>] = &[
122 Point::new(BTreeSet::from_iter([])),
123 Point::new(BTreeSet::from_iter([0])),
124 Point::new(BTreeSet::from_iter([1])),
125 Point::new(BTreeSet::from_iter([0, 1])),
126 ];
127
128 assert!(std::panic::catch_unwind(|| check_lattice_ord(items)).is_err());
130 assert!(std::panic::catch_unwind(|| check_partial_ord_properties(items)).is_err());
132 assert!(std::panic::catch_unwind(|| check_lattice_properties(items)).is_err());
134 }
135}