Type gymnastics of heterogeneously-typed lists
⚓ Rust 📅 2025-08-03 👤 surdeus 👁️ 11I'm designing a pass system inspired by frunk.
This is a little introduction of the Selector in frunk (click for more details)I design a pass trait as
trait Pass {
fn do_a<I>(pass_chain: &mut PC, ...)
where
PC: Selector<Self, I>;
fn do_b<I>(pass_chain: &mut PC, ...)
where
PC: Selector<Self, I>;
// ...
}
Where a pass chain would be something like a hlist containing different passes.
In the impl of each do_a, do_b, I want each pass can pass the execution towards other funcs in the same pass, or pass to next pass, or pass to the initial pass to redo the whole thing, which means I want each pass to have abilities to invoke do_a, do_b of current pass, next pass, and initial pass of the pass chain.
As a result, I modify the Selector trait like this:
pub trait Selector<S, I> {
type Next;
fn get_current(&self) -> &S;
fn get_current_mut(&mut self) -> &mut S;
fn get_next(&self) -> &Self::Next;
fn get_next_mut(&mut self) -> &mut Self::Next;
}
impl<T, Tail> Selector<T, Here> for (T, Tail) {
type Next = Tail;
fn get_current(&self) -> &T {
let (head, _) = self;
head
}
fn get_current_mut(&mut self) -> &mut T {
let (head, _) = self;
head
}
fn get_next(&self) -> &Tail {
let (_, next) = self;
next
}
fn get_next_mut(&mut self) -> &mut Tail {
let (_, next) = self;
next
}
}
impl<Head, Tail, FromTail, TailIndex> Selector<FromTail, There<TailIndex>> for (Head, Tail)
where
Tail: Selector<FromTail, TailIndex>,
{
type Next = Tail::Next;
fn get_current(&self) -> &FromTail {
let (_, tail) = self;
tail.get_current()
}
fn get_current_mut(&mut self) -> &mut FromTail {
let (_, tail) = self;
tail.get_current_mut()
}
fn get_next(&self) -> &Tail::Next {
let (_, tail) = self;
tail.get_next()
}
fn get_next_mut(&mut self) -> &mut Tail::Next {
let (_, tail) = self;
tail.get_next_mut()
}
}
However, I could not find out how to write a generic bound for the Next element and PC, so that I could write codes like
impl Pass for PassA {
fn do_a<I>(pass_chain: &mut PC, ...)
where
PC: Selector<Self, I>
{
PC::Next::do_a(pass_chain, ...); // Let next passes do other things
PC::do_a(pass_chain, ...); // Redo the whole thing from the beginning of the chain
}
}
This problem has made me struggled for about two weeks. Any advice will be appreciated!
1 post - 1 participant
🏷️ Rust_feed