I'm currently working on a large rewrite on the crate simdeez which allows easy trait-based SIMD selection.
Each SIMD type implements a few traits that represents what operations it can perform. Everything works fine, except when I tried adding "where" constraints on operations associated with the underlying scalar.
Such as the constraint in this (stripped) example:
pub trait SimdBase: Copy
Self::Scalar: Sub<Self, Output = Self>,
Which would allow the user to do 1.0 - simd_value instead of S::Vf32::set1(1.0) - simd_value (where S is the current SIMD instruction set generic).
The above example works fine, however when I add similar constraints onto other subtypes, I get errors that I can't seem to solve. The compiler recommends adding another where clause but it doesn't work at all.
Here's a minimal reproduction of my problem:
I can't add the Div constraint onto the SimdBase trait as only floating point values are able to perform division in the majority of SIMD. I've tried applying the compiler suggestion of course, but it doesn't appear to work.
Am I missing something, or is this a limitation of the compiler?
Huh, it appears that even the constraints that work correctly don't propagate around properly.
E.g. the trait that represents the current SIMD instruction set has associated types for each scalar type representation, however 1.0 - simd_value doesn't work unless I add the same "where" constraints onto those associated types as well, even though the trait itself already specifies them.
Not really, Float isn't needed because SimdBase::Scalar already specifies the type. And basically everything relies on Scalar, so duplicating multiple fields like that would probably cause more issues.
The main thing I want is to mark that this trait has operator overloading. So I already have things like SimdFloat: Div<Self, Output = Self> + Div<Self::Scalar, Output = Self>, there should also somehow be Self::Scalar: Div<Self, Output = Self>
Ah yeah my bad, I do have a module called base, I got confused because I wouldn't be surprized if there was underlying nomenclature such as base to refer to an inherited trait, but yeah it makes sense now.
Anyway, I just noticed a bigger issue. My first playground link actually isn't the full picture, because the associated types actually reference each other. Here is a more complete playground link (implementing your solution as well):
There appears to be an issue with cyclical dependencies and it makes sense why, I'm just not sure if it's physically possible to solve this one.