Constraining const generics

I have a struct:

#[derive(Debug, PartialEq, Eq)]
enum Type {
    Static(usize),
    Dynamic
}

struct Tensor<const D1: Type> {}

and an implementation of Mul:

default impl <const D1: Type, const D2: usize>Mul<&Tensor<{Type::Static(D2)}>> for Tensor<D1> {
    default type Output = Tensor<D1>;

    default fn mul(self, rhs: &Tensor<{static_dim(D2)}>) -> Self::Output {
        todo!()
    }
}

This throws an error: the const parameter D2 is not constrained by the impl trait, self type, or predicates

How can I constrain D2 here?

Looks like this might not be possible. The compiler would need to have some understanding of the fact that the type::Static constructor is injective, i.e. that the resulting Type uniquely determines the passed usize. Without this understanding, the compiler conservatively assumes that an expression like {Type::Static(D2)} might produce the same result for different values of D2, in which case there would be multiple conflicting implementations for the same trait bound.

1 Like

Is there any way to basically specialize Mul for two cases, one with any Type and one with Static(1)? Something like this:

default impl <const D1: Type, const D2: Type>Mul<&Tensor<D2>> for Tensor<D1> {
    default type Output = Tensor<D1>;

    default fn mul(self, rhs: &Tensor<D2>) -> Self::Output {
        todo!()
    }
}

impl <const D1: Type>Mul<&Tensor<{Type::Static(1)}>> for Tensor<D1> {
   type Output = Tensor<D1>;

   fn mul(self, rhs: &Tensor<{Type::Static(1)}>) -> Self::Output {
        todo!()
    }
}

Not sure why specialization wouldn't work for this.