Apologies if this falls under "help" more than an IRLO discussion, but this is weird enough people have suggested filing a bug and I wanted to see if anyone could explain what's happening before I do that.
The following example doesn't work:
use core::ops::Mul;
// Don't touch this
pub trait Group:
Sized
+ Mul<Self::Scalar, Output = Self>
+ for<'a> Mul<&'a Self::Scalar, Output = Self>
{
type Scalar;
}
// Make changes to anything below
pub trait Curve {
type Scalar;
type Field;
}
pub struct Point<C: Curve> {
x: C::Field,
y: C::Field
}
impl<C: Curve> Group for Point<C> {
type Scalar = C::Scalar;
}
impl<C: Curve> Mul<C::Scalar> for Point<C> {
type Output = Self;
fn mul(self, other: C::Scalar) -> Self {
unimplemented!()
}
}
impl<C: Curve> Mul<&C::Scalar> for Point<C> {
type Output = Self;
fn mul(self, other: &C::Scalar) -> Self {
unimplemented!()
}
}
It fails to typecheck with the following error:
error[E0119]: conflicting implementations of trait `std::ops::Mul<&_>` for type `Point<_>`
--> src/lib.rs:37:1
|
29 | impl<C: Curve> Mul<C::Scalar> for Point<C> {
| ------------------------------------------ first implementation here
...
37 | impl<C: Curve> Mul<&C::Scalar> for Point<C> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Point<_>`
...but if instead of C::Scalar
I use a concrete type like a struct
, the Mul
impls do not conflict.
The error seems to suggest that an associated type could be its own reference type? I'm quite confused by it. I know that generic parameters of traits are a weird corner case in the orphan rules, but I can't figure out what's happening here.
If I remove the second Mul
impl, it quickly becomes clear these two types are distinct:
error[E0271]: type mismatch resolving `for<'a> <C as Curve>::Scalar == &'a <C as Curve>::Scalar`
--> src/lib.rs:25:16
|
25 | impl<C: Curve> Group for Point<C> {
| ^^^^^ expected associated type, found reference
|
= note: expected associated type `<C as Curve>::Scalar`
found reference `&'a <C as Curve>::Scalar`
= help: consider constraining the associated type `<C as Curve>::Scalar` to `&'a <C as Curve>::Scalar`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
Is the original error about overlapping Mul
definitions a bug, or expected behavior for some reason?