I have a type IntPair<T>
which is generic over the type of some of its elements. The element type T
may be some minimally restrictive type (Int64
), or some more restrictive type which provides more guarantees (Int32
, which in this case guarantees a reduced range of possible values).
The more restrictive element type implements Into
the less restrictive element type. I want this conversion to generically carry into the type IntPair<T>
which uses the other type as elements.
Here's an example:
pub struct Int32(pub i32);
pub struct Int64(pub i64);
impl Into<Int64> for Int32 {
fn into(self) -> Int64 {
Int64(self.0 as i64)
}
}
pub struct IntPair<T> {
pub x: T,
pub y: T,
}
impl<T: Into<Int64>> Into<IntPair<Int64>> for IntPair<T> {
fn into(self) -> IntPair<Int64> {
IntPair {
x: self.x.into(),
y: self.y.into(),
}
}
}
fn main() {
let p32: IntPair<Int32> = IntPair {
x: Int32(3),
y: Int32(9),
};
let p64: IntPair<Int64> = p32.into();
}
Unfortunately, this code does not work.
error[E0119]: conflicting implementations of trait `std::convert::Into<IntPair<Int64>>` for type `IntPair<_>`:
--> src/main.rs:12:1
|
12 | impl<T: Into<Int64>> Into<IntPair<Int64>> for IntPair<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T, U> std::convert::Into<U> for T
where U: std::convert::From<T>;
If I understand, the compiler cannot guarantee that there isn't an impl of From<IntPair<T>> for IntPair<Int64>
, which would trigger a conflicting impl of Into<IntPair<Int64>> for IntPair<T>
, due to IntPair<T>
not being a concrete type.
That makes sense, but I would still like this feature. The only solution I can think of would be to create my own trait which behaves the same as Into
. However, that would not be ideal, as the type would not work for methods that accept impl Into<IntPair<Int64>>
.
Is there a way I can make this impl compile?