Skip to content

Commit bebe212

Browse files
Allow Relation<T> to be joined with Variable<(T, S)>
This case occurred in `Polonius`, where we had to create a separate `Relation<(T, ())>` to make things work. Implementing this required a change to the interface of `JoinInput`, since we are not allowed to assume that a `Relation<T>` and a `Relation<(T, ())>` are layout compatible. Now, `stable` takes a callback instead of returning a slice directly.
1 parent 3d18dec commit bebe212

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

src/join.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ fn join_delta<'me, Key: Ord, Val1: Ord, Val2: Ord>(
5151
let recent1 = input1.recent();
5252
let recent2 = input2.recent();
5353

54-
for batch2 in input2.stable().iter() {
54+
input2.for_each_stable_set(|batch2| {
5555
join_helper(&recent1, &batch2, &mut result);
56-
}
56+
});
5757

58-
for batch1 in input1.stable().iter() {
58+
input1.for_each_stable_set(|batch1| {
5959
join_helper(&batch1, &recent2, &mut result);
60-
}
60+
});
6161

6262
join_helper(&recent1, &recent2, &mut result);
6363
}
@@ -164,40 +164,56 @@ pub trait JoinInput<'me, Tuple: Ord>: Copy {
164164
/// empty slice.)
165165
type RecentTuples: Deref<Target = [Tuple]>;
166166

167-
/// If we are on iteration N of the loop, these are the tuples
168-
/// added on iteration N - 2 or before. (For a `Relation`, this is
169-
/// just `self`.)
170-
type StableTuples: Deref<Target = [Relation<Tuple>]>;
171-
172167
/// Get the set of recent tuples.
173168
fn recent(self) -> Self::RecentTuples;
174169

175-
/// Get the set of stable tuples.
176-
fn stable(self) -> Self::StableTuples;
170+
/// Call a function for each set of stable tuples.
171+
fn for_each_stable_set(self, f: impl FnMut(&[Tuple]));
177172
}
178173

179174
impl<'me, Tuple: Ord> JoinInput<'me, Tuple> for &'me Variable<Tuple> {
180175
type RecentTuples = Ref<'me, [Tuple]>;
181-
type StableTuples = Ref<'me, [Relation<Tuple>]>;
182176

183177
fn recent(self) -> Self::RecentTuples {
184178
Ref::map(self.recent.borrow(), |r| &r.elements[..])
185179
}
186180

187-
fn stable(self) -> Self::StableTuples {
188-
Ref::map(self.stable.borrow(), |v| &v[..])
181+
fn for_each_stable_set(self, mut f: impl FnMut(&[Tuple])) {
182+
for stable in self.stable.borrow().iter() {
183+
f(stable)
184+
}
189185
}
190186
}
191187

192188
impl<'me, Tuple: Ord> JoinInput<'me, Tuple> for &'me Relation<Tuple> {
193189
type RecentTuples = &'me [Tuple];
194-
type StableTuples = &'me [Relation<Tuple>];
195190

196191
fn recent(self) -> Self::RecentTuples {
197192
&[]
198193
}
199194

200-
fn stable(self) -> Self::StableTuples {
201-
std::slice::from_ref(self)
195+
fn for_each_stable_set(self, mut f: impl FnMut(&[Tuple])) {
196+
f(&self.elements)
197+
}
198+
}
199+
200+
impl<'me, Tuple: Ord> JoinInput<'me, (Tuple, ())> for &'me Relation<Tuple> {
201+
type RecentTuples = &'me [(Tuple, ())];
202+
203+
fn recent(self) -> Self::RecentTuples {
204+
&[]
205+
}
206+
207+
fn for_each_stable_set(self, mut f: impl FnMut(&[(Tuple, ())])) {
208+
use std::mem;
209+
assert_eq!(mem::size_of::<(Tuple, ())>(), mem::size_of::<Tuple>());
210+
assert_eq!(mem::align_of::<(Tuple, ())>(), mem::align_of::<Tuple>());
211+
212+
// SAFETY: https://rust-lang.github.io/unsafe-code-guidelines/layout/structs-and-tuples.html#structs-with-1-zst-fields
213+
// guarantees that `T` is layout compatible with `(T, ())`, since `()` is a 1-ZST.
214+
let elements: &'me [Tuple] = self.elements.as_slice();
215+
let elements: &'me [(Tuple, ())] = unsafe { std::mem::transmute(elements) };
216+
217+
f(elements)
202218
}
203219
}

0 commit comments

Comments
 (0)