I'm writing a type level Fibonacci sequence. I've already written a type level addition, which works fine. Every number is represented as Inc<Inc<...<Zero>...>>
. There is a trait Add
, then the structure Bop<Left, Right>
(binary operation) implements the Add
trait. The usage is that <Bop<Inc<Inc<Inc<Zero>>>, Inc<Inc<Zero>>> as Add>::Get
will be Inc<Inc<Inc<Inc<Inc<Zero>>>>>
, that is 3 + 2 = 5.
Then I write a Fibonacci sequence based on the addition:
use std::marker::PhantomData;
struct Zero {}
struct Inc<T> {
_phantom: PhantomData<T>,
}
struct Bop<Left, Right> {
_phantom_l: PhantomData<Left>,
_phantom_r: PhantomData<Right>,
}
trait Add {
type Get;
}
impl<Left> Add for Bop<Left, Zero> {
type Get = Left;
}
impl<Left, RightInner> Add for Bop<Left, Inc<RightInner>>
where
Bop<Left, RightInner>: Add,
{
type Get = Inc<<Bop<Left, RightInner> as Add>::Get>;
}
type One = Inc<Zero>;
type Two = Inc<One>;
type Three = Inc<Two>;
type Four = Inc<Three>;
type Five = Inc<Four>;
// then <Bop<Three, Two> as Add>::Get will be type Five
// 0 1 2 3 4 5 6 7
// 0 1 1 2 3 5 8 13
// usage: <Inc<Inc<Inc<Zero>>> as Fib>::Get should be the third fib number,
// i.e. 2, or Inc<Inc<Zero>>
trait Fib {
type Get;
}
impl Fib for Zero {
type Get = Zero;
}
impl Fib for One {
type Get = One;
}
impl<T> Fib for Inc<Inc<T>>
where
T: Fib,
Inc<T>: Fib,
Bop<<T as Fib>::Get, <Inc<T> as Fib>::Get>: Add,
{
type Get = <Bop<<T as Fib>::Get, <Inc<T> as Fib>::Get> as Add>::Get;
}
fn main() {}
The compiler has trouble figuring out the impl<T> Fib for Uop<Inc<Inc<T>>>
part, it complains:
error[E0275]: overflow evaluating the requirement `Inc<_>: Fib`
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<_>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<_>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<_>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<_>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Fib` for `Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<Inc<_>>>>>>>>>>>>>>`
// cut off more
What's the reason of the error? How to resolve it?