1use core::cmp::Ordering::{self, *};
2
3use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
4
5#[derive(Copy, Clone, Debug, Default, Eq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct DomPair<Key, Val> {
20 pub key: Key,
24 val: Val,
26}
27
28impl<Key, Val> DomPair<Key, Val> {
29 pub fn new(key: Key, val: Val) -> Self {
31 Self { key, val }
32 }
33
34 pub fn new_from(key: impl Into<Key>, val: impl Into<Val>) -> Self {
36 Self::new(key.into(), val.into())
37 }
38
39 pub fn as_reveal_ref(&self) -> (&Key, &Val) {
41 (&self.key, &self.val)
42 }
43
44 pub fn as_reveal_mut(&mut self) -> (&mut Key, &mut Val) {
46 (&mut self.key, &mut self.val)
47 }
48
49 pub fn into_reveal(self) -> (Key, Val) {
51 (self.key, self.val)
52 }
53}
54
55impl<Key, Val> DeepReveal for DomPair<Key, Val>
56where
57 Key: DeepReveal,
58 Val: DeepReveal,
59{
60 type Revealed = (Key::Revealed, Val::Revealed);
61
62 fn deep_reveal(self) -> Self::Revealed {
63 (self.key.deep_reveal(), self.val.deep_reveal())
64 }
65}
66
67impl<KeySelf, KeyOther, ValSelf, ValOther> Merge<DomPair<KeyOther, ValOther>>
68 for DomPair<KeySelf, ValSelf>
69where
70 KeySelf: Merge<KeyOther> + LatticeFrom<KeyOther> + PartialOrd<KeyOther>,
71 ValSelf: Merge<ValOther> + LatticeFrom<ValOther>,
72{
73 fn merge(&mut self, other: DomPair<KeyOther, ValOther>) -> bool {
74 match self.key.partial_cmp(&other.key) {
75 None => {
76 assert!(self.key.merge(other.key));
77 self.val.merge(other.val);
78 true
79 }
80 Some(Equal) => self.val.merge(other.val),
81 Some(Less) => {
82 *self = LatticeFrom::lattice_from(other);
83 true
84 }
85 Some(Greater) => false,
86 }
87 }
88}
89
90impl<KeySelf, KeyOther, ValSelf, ValOther> LatticeFrom<DomPair<KeyOther, ValOther>>
91 for DomPair<KeySelf, ValSelf>
92where
93 KeySelf: LatticeFrom<KeyOther>,
94 ValSelf: LatticeFrom<ValOther>,
95{
96 fn lattice_from(other: DomPair<KeyOther, ValOther>) -> Self {
97 Self {
98 key: LatticeFrom::lattice_from(other.key),
99 val: LatticeFrom::lattice_from(other.val),
100 }
101 }
102}
103
104impl<KeySelf, KeyOther, ValSelf, ValOther> PartialOrd<DomPair<KeyOther, ValOther>>
105 for DomPair<KeySelf, ValSelf>
106where
107 KeySelf: PartialOrd<KeyOther>,
108 ValSelf: PartialOrd<ValOther>,
109{
110 fn partial_cmp(&self, other: &DomPair<KeyOther, ValOther>) -> Option<Ordering> {
111 match self.key.partial_cmp(&other.key) {
112 Some(Equal) => self.val.partial_cmp(&other.val),
113 otherwise => otherwise,
114 }
115 }
116}
117impl<KeySelf, KeyOther, ValSelf, ValOther> LatticeOrd<DomPair<KeyOther, ValOther>>
118 for DomPair<KeySelf, ValSelf>
119where
120 Self: PartialOrd<DomPair<KeyOther, ValOther>>,
121{
122}
123
124impl<KeySelf, KeyOther, ValSelf, ValOther> PartialEq<DomPair<KeyOther, ValOther>>
125 for DomPair<KeySelf, ValSelf>
126where
127 KeySelf: PartialEq<KeyOther>,
128 ValSelf: PartialEq<ValOther>,
129{
130 fn eq(&self, other: &DomPair<KeyOther, ValOther>) -> bool {
131 if self.key != other.key {
132 return false;
133 }
134
135 if self.val != other.val {
136 return false;
137 }
138
139 true
140 }
141}
142
143impl<Key, Val> IsBot for DomPair<Key, Val>
144where
145 Key: IsBot,
146 Val: IsBot,
147{
148 fn is_bot(&self) -> bool {
149 self.key.is_bot() && self.val.is_bot()
150 }
151}
152
153impl<Key, Val> IsTop for DomPair<Key, Val>
154where
155 Key: IsTop,
156 Val: IsTop,
157{
158 fn is_top(&self) -> bool {
159 self.key.is_top() && self.val.is_top()
160 }
161}
162
163#[cfg(test)]
164mod test {
165 use std::collections::HashSet;
166
167 use super::*;
168 use crate::WithTop;
169 use crate::ord::Max;
170 use crate::set_union::SetUnionHashSet;
171 use crate::test::{
172 check_lattice_is_bot, check_lattice_is_top, check_lattice_ord, check_lattice_properties,
173 check_partial_ord_properties,
174 };
175
176 #[cfg(feature = "alloc")]
177 #[test]
178 fn consistency() {
179 use alloc::vec;
180 use alloc::vec::Vec;
181
182 let mut test_vec = Vec::new();
183
184 for a in [vec![], vec![0], vec![1], vec![0, 1]] {
185 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
186 test_vec.push(DomPair::new(
187 SetUnionHashSet::new_from(HashSet::from_iter(a.clone())),
188 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
189 ));
190 }
191 }
192
193 check_lattice_ord(&test_vec);
194 check_partial_ord_properties(&test_vec);
195 check_lattice_is_bot(&test_vec);
196 assert!(std::panic::catch_unwind(|| check_lattice_properties(&test_vec)).is_err());
198 }
199
200 #[cfg(feature = "alloc")]
201 #[test]
202 fn consistency_withtop() {
203 use alloc::vec;
204
205 let mut test_vec = vec![];
206
207 let sub_items = &[
208 Some(&[] as &[usize]),
209 Some(&[0]),
210 Some(&[1]),
211 Some(&[0, 1]),
212 None,
213 ];
214
215 for a in sub_items {
216 for b in sub_items {
217 test_vec.push(DomPair::new(
218 WithTop::new(
219 a.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
220 ),
221 WithTop::new(
222 b.map(|x| SetUnionHashSet::new_from(HashSet::from_iter(x.iter().cloned()))),
223 ),
224 ));
225 }
226 }
227
228 check_lattice_ord(&test_vec);
229 check_partial_ord_properties(&test_vec);
230 check_lattice_is_bot(&test_vec);
231 check_lattice_is_top(&test_vec);
232 assert!(std::panic::catch_unwind(|| check_lattice_properties(&test_vec)).is_err());
234 }
235
236 #[cfg(feature = "alloc")]
237 #[test]
238 fn consistency_with_ord_lhs() {
239 use alloc::vec;
240 use alloc::vec::Vec;
241
242 let mut test_vec = Vec::new();
243
244 for a in [0, 1, 2] {
245 for b in [vec![], vec![0], vec![1], vec![0, 1]] {
246 test_vec.push(DomPair::new(
247 Max::new(a),
248 SetUnionHashSet::new_from(HashSet::from_iter(b.clone())),
249 ));
250 }
251 }
252
253 check_lattice_ord(&test_vec);
254 check_lattice_properties(&test_vec);
255 check_partial_ord_properties(&test_vec);
256 }
257}