Nested generic trait parameter gives "unconstrained type parameter"

Viewed 120

Consider the next snippet:

trait GenericTrait<T> {
    fn value(&self) -> T;
}

struct GenericStruct<U> {
    field: U,
}

impl<T: PartialEq, U: GenericTrait<T>> PartialEq for GenericStruct<U> {
    fn eq(&self, other: &Self) -> bool {
        <U as GenericTrait<T>>::value(&self.field) == <U as GenericTrait<T>>::value(&other.field)
    }
}

it gives me

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/lib.rs:34:6
   |
34 | impl<T: PartialEq, U: GenericTrait<T>> PartialEq for GenericStruct<U> {
   |      ^ unconstrained type parameter

For more information about this error, try `rustc --explain E0207`.

Ok, if I add this trait to GenericStruct definition

struct GenericStruct<T, U: GenericTrait<T>> {
    field: U,
}

I'm getting

error[E0392]: parameter `T` is never used
  --> src/lib.rs:30:22
   |
30 | struct GenericStruct<T, U: GenericTrait<T>> {
   |                      ^ unused parameter
   |
   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
   = help: if you intended `T` to be a const parameter, use `const T: usize` instead

For more information about this error, try `rustc --explain E0392`.

So, am I forced to add a "dummy" field to a GenericStruct like

struct GenericStruct<T, U: GenericTrait<T>> {
    field: U,
    _dummy: PhantomData<*const T>,
}

to make it work or is there some better approach to this problem?

1 Answers

Use an associated type instead of generics:

trait GenericTrait {
    type Output;
    fn value(&self) -> Self::Output;
}

struct GenericStruct<U> {
    field: U,
}

impl<T: PartialEq, U: GenericTrait<Output=T>> PartialEq for GenericStruct<U> {
    fn eq(&self, other: &Self) -> bool {
        <U as GenericTrait>::value(&self.field) == <U as GenericTrait>::value(&other.field)
    }
}

Playground

Related