Implementation of trait for a trait [E0207]

Hello

I have some difficulties to implement a trait.
I have define a trait Tensor and I do not manage to implement the Add trait. I get the error E0207.
Does somebody has any idea how to solve this problem?


use std::collections::*;
use std::hash::*;
use std::ops::Add;

type Int = i32;
type Real = f64;
type Size = usize;


trait Tensor<K, V> {
	fn size(&self) -> Size;
	fn apply(&self, k :K) -> V;
	fn update(&mut self, k :K, v :V);
}


impl <V2, V1 :Add<V2>, C :Tensor<Size, V1>> Add<V2> for C {
	type Output = C;
	
	fn add(self, rhs: V2) -> C {
		self.apply(0) + rhs;
        println!("add");
        self
    } 
}

The error message is

Thanks

Sebastien

Minor style issue: k: K, not k :K, is the official style (and it looks like your mixed tabs and spaces got mangled by discourse).

As for the error, it's pretty much what it says on the tin: V1 is not constrained, so <X as Add<Y>> would have less/more than exactly one choice for V1 (I do wish this error was clearer).

One way you might be able to fix this is make K and V associated types of Tensor, i.e. each type implementing Tensor only gets exactly one choice for K and one for V.

The code would then look like:

trait Tensor {
    type K;
    type V;
    fn size(&self) -> Size;
    fn apply(&self, k: Self::K) -> Self::V;
    fn update(&mut self, k: Self::K, v: Self::V);
}

impl <V2, C: Tensor<K=Size>> Add<V2> for C
where C::V: Add<V2> {
    type Output = C;
    fn add(self, rhs: V2) -> C {
        self.apply(0) + rhs;
        println!("add");
        self
    }
}

But that would still not compile, as Tensor could be independently implemented for types that also implement Add and that's disallowed by Rust's coherence checks:
"error: type parameter C must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter [E0210]"

I'm afraid you'll have to implement Add and other traits for each tensor type manually (I'd suggest using macros to make that easier).

Hello all !

Bumping this since I stumble upon this issue as well.

trait GenericTrait<A> {}
trait OtherTrait {}

// error[E0207]: the type parameter `A` is not constrained
// by the impl trait, self type, or predicates
impl<T, A> OtherTrait for T
where
    T: GenericTrait<A>
{}

playground / reddit

Is there a way to do this when traits are generic?

Thanks

You can’t do exactly that in current Rust, but there area few closely-related options:

  • You can require a particular type for the GenericTrait parameter:
impl<T> OtherTrait for T where T:GenericTrait<usize> {}
  • You can make GenericTrait use an associated type instead of a type parameter, which restricts A to a single type chosen by the impl GenericTrait block:
trait GenericTrait {
    type A;
}

impl<T> OtherTrait for T where T: GenericTrait {}
  • You can make OtherTrait generic in A:
impl<T,A> OtherTrait<A> for T where T: GenericTrait<A>

Thanks bro,

I found my way by wrapping the generic trait into a type, as explained somewhere in the official docs. Implementation is specific to my use case I guess, but totally was the way to go.

trait GenericTrait<A> {}
trait OtherTrait {}
struct S<T, A>(T, A /* You can also std::marker::PhantomData */) where T: GenericTrait<A>;

impl<T, A> OtherTrait for S<T, A>
where T: GenericTrait<A>
{}