Heres a simple example of the problem I ran into recently.
mod external_crate {
pub use std::ops::Mul;
pub trait Scalar {
fn bytes(&self) -> &[u8];
}
pub trait Base {
type Scalar: Scalar;
type Projective: ScalarMul<Scalar = Self::Scalar>;
}
pub trait ScalarMul: for<'a> Mul<&'a Self::Scalar> + Mul<Self::Scalar> {
type Scalar: Scalar;
}
}
use external_crate::*;
struct ConcreteProjective<B>(B);
impl<B: Base> ScalarMul for ConcreteProjective<B> {
type Scalar = <B as Base>::Scalar;
}
/// This is not sufficient to satisfy the trait.
impl<B: Base> Mul<B::Scalar> for ConcreteProjective<B> {
type Output = Self;
fn mul(self, rhs: B::Scalar) -> Self {
todo!()
}
}
/// This gives a compiler error about conflicting impls.
impl<'a, B: Base> Mul<&'a B::Scalar> for ConcreteProjective<B> {
type Output = Self;
fn mul(self, rhs: &'a B::Scalar) -> Self {
todo!()
}
}
I have a solution already, which is to force ScalarMul<Scalar = Scalar<B>>
to be some concrete type where Scalar
is struct Scalar<B: Base>(B::Scalar)
so im mostly curious in classifying the issue, and understanding if there are already plans to fix this.