Skip to content

Commit 5112400

Browse files
authored
PartialOrder with Rhs type parameter (#565)
* PartialOrder generic over right-hand side Change the `PartialOrder` trait to have an optional right-hand side type. This allows us to implement partial order for unequal types, which comes in handy when working with complex timestamp times that a container might store as a GAT instead of the actual type. Signed-off-by: Moritz Hoffmann <[email protected]> * Address feedback Signed-off-by: Moritz Hoffmann <[email protected]> --------- Signed-off-by: Moritz Hoffmann <[email protected]>
1 parent f3ca4ba commit 5112400

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

timely/src/order.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
/// This trait is distinct from Rust's `PartialOrd` trait, because the implementation
66
/// of that trait precludes a distinct `Ord` implementation. We need an independent
77
/// trait if we want to have a partially ordered type that can also be sorted.
8-
pub trait PartialOrder : Eq {
8+
pub trait PartialOrder<Rhs: ?Sized = Self>: PartialEq<Rhs> {
99
/// Returns true iff one element is strictly less than the other.
10-
fn less_than(&self, other: &Self) -> bool {
10+
fn less_than(&self, other: &Rhs) -> bool {
1111
self.less_equal(other) && self != other
1212
}
1313
/// Returns true iff one element is less than or equal to the other.
14-
fn less_equal(&self, other: &Self) -> bool;
14+
fn less_equal(&self, other: &Rhs) -> bool;
1515
}
1616

1717
/// A type that is totally ordered.
@@ -97,9 +97,14 @@ mod product {
9797
}
9898

9999
use super::PartialOrder;
100-
impl<TOuter: PartialOrder, TInner: PartialOrder> PartialOrder for Product<TOuter, TInner> {
100+
impl<TOuter, TOuter2, TInner, TInner2> PartialOrder<Product<TOuter2, TInner2>> for Product<TOuter, TInner>
101+
where
102+
TOuter: PartialOrder<TOuter2>,
103+
TInner: PartialOrder<TInner2>,
104+
Self: PartialEq<Product<TOuter2, TInner2>>,
105+
{
101106
#[inline]
102-
fn less_equal(&self, other: &Self) -> bool {
107+
fn less_equal(&self, other: &Product<TOuter2, TInner2>) -> bool {
103108
self.outer.less_equal(&other.outer) && self.inner.less_equal(&other.inner)
104109
}
105110
}
@@ -189,9 +194,14 @@ mod product {
189194
mod tuple {
190195

191196
use super::PartialOrder;
192-
impl<TOuter: PartialOrder, TInner: PartialOrder> PartialOrder for (TOuter, TInner) {
197+
impl<TOuter, TOuter2, TInner, TInner2> PartialOrder<(TOuter2, TInner2)> for (TOuter, TInner)
198+
where
199+
TOuter: PartialOrder<TOuter2>,
200+
TInner: PartialOrder<TInner2>,
201+
(TOuter, TInner): PartialEq<(TOuter2, TInner2)>,
202+
{
193203
#[inline]
194-
fn less_equal(&self, other: &Self) -> bool {
204+
fn less_equal(&self, other: &(TOuter2, TInner2)) -> bool {
195205
// We avoid Rust's `PartialOrd` implementation, for reasons of correctness.
196206
self.0.less_than(&other.0) || (self.0.eq(&other.0) && self.1.less_equal(&other.1))
197207
}

timely/src/progress/frontier.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,32 @@ impl<T: PartialOrder> Antichain<T> {
6969
}
7070
}
7171

72+
/// Updates the `Antichain` if the element is not greater than or equal to some present element.
73+
/// If the antichain needs updating, it uses the `to_owned` closure to convert the element into
74+
/// a `T`.
75+
///
76+
/// Returns true if element is added to the set
77+
///
78+
/// # Examples
79+
///
80+
///```
81+
/// use timely::progress::frontier::Antichain;
82+
///
83+
/// let mut frontier = Antichain::new();
84+
/// assert!(frontier.insert_with(&2, |x| *x));
85+
/// assert!(!frontier.insert(3));
86+
///```
87+
pub fn insert_with<O: PartialOrder<T>, F: FnOnce(&O) -> T>(&mut self, element: &O, to_owned: F) -> bool where T: PartialOrder<O> {
88+
if !self.elements.iter().any(|x| x.less_equal(element)) {
89+
self.elements.retain(|x| !element.less_equal(x));
90+
self.elements.push(to_owned(element));
91+
true
92+
}
93+
else {
94+
false
95+
}
96+
}
97+
7298
/// Reserves capacity for at least additional more elements to be inserted in the given `Antichain`
7399
pub fn reserve(&mut self, additional: usize) {
74100
self.elements.reserve(additional);
@@ -450,9 +476,9 @@ impl<T> MutableAntichain<T> {
450476
/// assert!(frontier.less_than(&2));
451477
///```
452478
#[inline]
453-
pub fn less_than(&self, time: &T) -> bool
479+
pub fn less_than<O>(&self, time: &O) -> bool
454480
where
455-
T: PartialOrder,
481+
T: PartialOrder<O>,
456482
{
457483
self.frontier().less_than(time)
458484
}
@@ -470,9 +496,9 @@ impl<T> MutableAntichain<T> {
470496
/// assert!(frontier.less_equal(&2));
471497
///```
472498
#[inline]
473-
pub fn less_equal(&self, time: &T) -> bool
499+
pub fn less_equal<O>(&self, time: &O) -> bool
474500
where
475-
T: PartialOrder,
501+
T: PartialOrder<O>,
476502
{
477503
self.frontier().less_equal(time)
478504
}
@@ -549,9 +575,9 @@ impl<T> MutableAntichain<T> {
549575
}
550576

551577
/// Reports the count for a queried time.
552-
pub fn count_for(&self, query_time: &T) -> i64
578+
pub fn count_for<O>(&self, query_time: &O) -> i64
553579
where
554-
T: Ord,
580+
T: PartialEq<O>,
555581
{
556582
self.updates
557583
.unstable_internal_updates()
@@ -679,7 +705,7 @@ impl<'a, T: 'a> AntichainRef<'a, T> {
679705
}
680706
}
681707

682-
impl<'a, T: 'a+PartialOrder> AntichainRef<'a, T> {
708+
impl<T> AntichainRef<'_, T> {
683709

684710
/// Returns true if any item in the `AntichainRef` is strictly less than the argument.
685711
///
@@ -694,7 +720,7 @@ impl<'a, T: 'a+PartialOrder> AntichainRef<'a, T> {
694720
/// assert!(frontier.less_than(&2));
695721
///```
696722
#[inline]
697-
pub fn less_than(&self, time: &T) -> bool {
723+
pub fn less_than<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
698724
self.iter().any(|x| x.less_than(time))
699725
}
700726

@@ -711,7 +737,7 @@ impl<'a, T: 'a+PartialOrder> AntichainRef<'a, T> {
711737
/// assert!(frontier.less_equal(&1));
712738
/// assert!(frontier.less_equal(&2));
713739
///```
714-
pub fn less_equal(&self, time: &T) -> bool {
740+
pub fn less_equal<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
715741
self.iter().any(|x| x.less_equal(time))
716742
}
717743
}

0 commit comments

Comments
 (0)