 # Trait bounds being dropped?

I'm learning Rust, and trying to implement simple mathematical constructs. For a vector space, one would like to implement `Mul<scalar, Output = scalar>` and `Mul<vector, output = vector>` for scalars. With concrete types this is straightforward.

I attempted to write a simple generic implementation, where some trait knows the scalar and vector types and enforces the appropriate trait bounds, and wrote a trivial test function:

``````use std::ops::Mul;

pub trait VectorSpace {
type V;
type S: Mul<Self::S, Output = Self::S> + Mul<Self::V, Output = Self::V>;
//  type S: Mul<Self::V, Output = Self::V> + Mul<Self::S, Output = Self::S>;
}

fn test<VS: VectorSpace>(v: VS::V, k: VS::S) {
k * k;
k * v;
}
``````

gives

``````error[E0308]: mismatched types
--> src/lib.rs:12:9
|
12 |     k * k;
|         ^ expected VectorSpace::V, found VectorSpace::S
``````

This seems odd, since the trait bound `Mul<Self::S, Output = Self::S>` is present.

What's stranger is that if the trait bounds are swapped in order (ie. the commented out line), the type mismatch moves.

``````error[E0308]: mismatched types
--> src/lib.rs:13:9
|
13 |     k * v;
|         ^ expected VectorSpace::S, found VectorSpace::V
``````

From the testing I've been able to do, it seems as if in this case the lexically last `Mul<>` trait bound is preventing the others from being used. This also happens when the first `Mul` comes from some supertrait, which seems really weird. I don't know what traits someone else's supertraits might have defined, and being able to break them by specifying additional traits seems very odd.

Any help understanding what's going on would be really welcome.

I wondered whether the compiler doesn't like the two trait bounds potentially overlap, since the compiler can't prove `Self::S` and `Self::V` are distinct. In that case I'd have expected to catch an error in the definition of `VectorSpace`, as you do when you write overlapping trait implementations.

1 Like

Constraint resolution on associated types seems to be quite buggy in general, see for example this issue which has hit many users over time (including me): https://github.com/rust-lang/rust/issues/24159

There's supposed to be a new type / constraint resolution implementation coming, we may have to wait until then.