Classifying issue about HRTBs on generic GATs

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.

I'd say this is a coherence/overlap check issue than a HRTB/GAT issue. The compiler doesn't recognize these as non-overlapping.

impl<B: Base> Mul<B::Scalar> for ConcreteProjective<B> {
impl<'a, B: Base> Mul<&'a B::Scalar> for ConcreteProjective<B> {

This is related, as you basically want an associated-type-aware occurs-check in coherence.

I'm not aware of any plans.


Here's a workaround for this particular case:

impl<T, B: Base> Mul<T> for ConcreteProjective<B>
where
    T: std::borrow::Borrow<B::Scalar>
{
    type Output = Self;

    fn mul(self, rhs: T) -> Self {
        todo!()
    }
}

Thats a great workaround thank you!