Which exact types? If we required specific types, we’d need some way to inform the compiler of them, and the specificity requirement would imply that there’s exactly one type that can be used? If so, that would impose the requirement that there’s only one definition of SIMD types in a given tree of dependencies, and I really really don’t want that requirement. (For one, I personally don’t expect to get everything right first time, so it’d be very good if people are free to experiment themselves without “accidental”/arbitrary restrictions.)
I’m moderately concerned that introducing a vein of “relaxed” typing into the compiler will leave the door open for abuse/crazy tricks, but I’m unsure. However it seems quite restricted, so it’s not clear to me that one can do anything even slightly useful with it. Note, in practice, people using SIMD won’t need to worry about this at all: libraries will define things to ensure type safety (even at the intrinsic level).
NB. for the platform specific intrinsics we can/will require that they aren’t generic, so can type-check them in the type checker, properly (properly == answering is this a SIMD type of the appropriate length with the appropriate element type?). Hence, this discussion is basically the difference between being able to write fn simd_shuffle2<T, U>(v: T, w: T, ...) -> Simd2<U> and having the option to impose type safety (which is what will happen in practice), or being forced to have scheme by which the compiler can be totally assured that things will work. This would either require writing separate shuffle/comparison intrinsics for every concrete SIMD type, or would require compiler-known traits (like #[simd_primitive_trait], but also at least one more, I think) with some compulsory associated types and so on.
#[simd_primitive_trait]
trait SimdPrim {
type Bool: SimdPrim;
}
#[simd_vector_trait]
trait SimdVector {
type Elem: SimdPrim;
type Bool: SimdVector<Elem = Self::Elem::Bool>;
}
#[repr(simd)]
struct Simd2<T: SimdPrim>(T, T);
impl<T: SimdPrim> SimdVector for Simd2<T> {
type Elem = T;
type Bool = Simd2<T::Bool>;
}
extern {
fn simd_shuffle2<T: SimdVector>(v: T, w: T, i0: u32, i1: u32) -> Simd2<T::Elem>;
// ...
fn simd_lt<T: SimdVector>(v: T, w: T) -> T::Bool;
// ...
}
We’d need to have careful restrictions about how the implementations of SimdPrim and SimdVector can work, and especially around generic types. It seems very complicated, and I’m not sure it’s worth it.