| //@ build-pass | |
| #![allow(incomplete_features)] | |
| #![feature(generic_const_exprs)] | |
| trait Collate<Op> { | |
| type Pass; | |
| type Fail; | |
| fn collate(self) -> (Self::Pass, Self::Fail); | |
| } | |
| impl<Op> Collate<Op> for () { | |
| type Pass = (); | |
| type Fail = (); | |
| fn collate(self) -> ((), ()) { | |
| ((), ()) | |
| } | |
| } | |
| trait CollateStep<X, Prev> { | |
| type Pass; | |
| type Fail; | |
| fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail); | |
| } | |
| impl<X, P, F> CollateStep<X, (P, F)> for () { | |
| type Pass = (X, P); | |
| type Fail = F; | |
| fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) { | |
| ((x, p), f) | |
| } | |
| } | |
| struct CollateOpImpl<const MASK: u32>; | |
| trait CollateOpStep { | |
| type NextOp; | |
| type Apply; | |
| } | |
| impl<const MASK: u32> CollateOpStep for CollateOpImpl<MASK> | |
| where | |
| CollateOpImpl<{ MASK >> 1 }>: Sized, | |
| { | |
| type NextOp = CollateOpImpl<{ MASK >> 1 }>; | |
| type Apply = (); | |
| } | |
| impl<H, T, Op: CollateOpStep> Collate<Op> for (H, T) | |
| where | |
| T: Collate<Op::NextOp>, | |
| Op::Apply: CollateStep<H, (T::Pass, T::Fail)>, | |
| { | |
| type Pass = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Pass; | |
| type Fail = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Fail; | |
| fn collate(self) -> (Self::Pass, Self::Fail) { | |
| <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::collate_step(self.0, self.1.collate()) | |
| } | |
| } | |
| fn collate<X, const MASK: u32>(x: X) -> (X::Pass, X::Fail) | |
| where | |
| X: Collate<CollateOpImpl<MASK>>, | |
| { | |
| x.collate() | |
| } | |
| fn main() { | |
| dbg!(collate::<_, 5>(("Hello", (42, ('!', ()))))); | |
| } |