Associated type equality is unproven in trait method

Hello,

I have a rather complicated trait Reversible. However, there are preset implementations of it, and when one implements ReversibleHelper by picking fitting associated types, Reversible is implemented as well.

Howeve I can't get that to work. It seems like, while assigning the associated type of one to the other, that equality is forgotten when I try to pass that type from the function of one type to the other.

trait ReversibleBase: Reversible<Self> {}
trait Reversible<T: ?Sized + ReversibleBase> {
    type OneOfTheTypes;
    fn one_of_the_fns(x: Self::OneOfTheTypes);
}
trait ReversibleHelper: ReversibleBase
where
    HelperTuple<Self>: Reversible<Self>,
{
    type Breakpoints;
    type Continuity;
    type Acceleratable;
}
type HelperTuple<T> = (
    <T as ReversibleHelper>::Breakpoints,
    <T as ReversibleHelper>::Continuity,
    <T as ReversibleHelper>::Acceleratable,
);

//blanket impl
impl<T> Reversible<T> for T
where
    T: ReversibleBase + ReversibleHelper,
    HelperTuple<T>: Reversible<T>,
{
    type OneOfTheTypes = <HelperTuple<T> as Reversible<T>>::OneOfTheTypes;
    fn one_of_the_fns(x: Self::OneOfTheTypes) {
        <HelperTuple<T> as Reversible<T>>::one_of_the_fns(x);
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/lib.rs:28:59
   |
21 | impl<T> Reversible<T> for T
   |      - this type parameter
...
28 |         <HelperTuple<T> as Reversible<T>>::one_of_the_fns(x);
   |         ------------------------------------------------- ^ expected `(<... as ReversibleHelper>::Breakpoints, ..., ...)`, found type parameter `T`
   |         |
   |         arguments to this function are incorrect
   |
   = note: expected associated type `<(<T as ReversibleHelper>::Breakpoints, <T as ReversibleHelper>::Continuity, <T as ReversibleHelper>::Acceleratable) as Reversible<T>>::OneOfTheTypes`
              found associated type `<T as Reversible<T>>::OneOfTheTypes`
   = note: an associated type was expected, but a different one was found
note: associated function defined here
  --> src/lib.rs:4:8
   |
4  |     fn one_of_the_fns(x: Self::OneOfTheTypes);
   |        ^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (lib) due to previous error

Am I doing something wrong? Is this a compiler limitation?

This seems to be comparable, it is from an older approach.

pub trait Assoc {
    type Type;
}

pub trait Yak: Sized {
    type YakType: Bound<Self>;
    fn take_yak(value: Self::YakType);
}
    
impl<T: Assoc + YakHelper<T::Type>> Yak for T {
    type YakType = T::YakHelperType;
    fn take_yak(value: Self::YakType) {
        T::take_yak_helper(value)
    }
}

pub trait YakHelper<Type>: Yak {
    type YakHelperType: Bound<Self>;
    fn take_yak_helper(value: Self::YakHelperType);
}

trait Bound<T> {}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
  --> src/lib.rs:13:28
   |
13 |         T::take_yak_helper(value) //error
   |         ------------------ ^^^^^ expected `YakHelper::YakHelperType`, found `Yak::YakType`
   |         |
   |         arguments to this function are incorrect
   |
   = note: expected associated type `<T as YakHelper<<T as Assoc>::Type>>::YakHelperType`
              found associated type `<T as Yak>::YakType`
   = note: an associated type was expected, but a different one was found
note: associated function defined here
  --> src/lib.rs:19:8
   |
19 |     fn take_yak_helper(value: Self::YakHelperType);
   |        ^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (lib) due to previous error

I minimized the second example.

This causes the error:

pub trait Yak {
    type YakType;
    fn take_yak(value: Self::YakType);
}

pub trait YakHelper: Yak {
    type YakHelperType;
    fn take_yak_helper(value: Self::YakHelperType);
}
    
impl<T: YakHelper> Yak for T {
    type YakType = T::YakHelperType;
    fn take_yak(value: Self::YakType) {
        T::take_yak_helper(value)
    }
}

This (where I removed the bound Yak at YakHelper) makes it compile:

pub trait Yak {
    type YakType;
    fn take_yak(value: Self::YakType);
}

pub trait YakHelper/*: Yak*/ {
    type YakHelperType;
    fn take_yak_helper(value: Self::YakHelperType);
}
    
impl<T: YakHelper> Yak for T {
    type YakType = T::YakHelperType;
    fn take_yak(value: Self::YakType) {
        T::take_yak_helper(value)
    }
}

(From the OP)

This compiles, but I'm not convinced it will work if you actually try to use it. You can give it a shot though.

Sadly the compiler gets into a recursion with that one.

Here is your attempt with a test case below:

It seems I really need to get rid of the Bound on ReversibleBase here. I think that is doable in my case, I will just bound usages not to T: ReversibleBase but to T: ReversibleBase + Reversible<T> or I introduce a supertrait bundling the two.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.