0

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Phoenix
  • 1,553
  • 2
  • 13
  • 29
  • Implement `From` for the reverse direction, that's how it is supposed to work. – starblue Oct 12 '18 at 17:23
  • I believe your question is answered by the answers of [How is there a conflicting implementation of `From` when using a generic type?](https://stackoverflow.com/q/37347311/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Oct 12 '18 at 18:13
  • I'm taking a look at it now. – Phoenix Oct 12 '18 at 18:14
  • @starblue your suggestion does not appear to work. https://play.rust-lang.org/?gist=f5a326790f41ebb292a2a8f6f22d429c&version=stable&mode=debug&edition=2015 – Phoenix Oct 12 '18 at 18:17
  • 1
    @shepmaster you're welcome to mark this question as answered. – Phoenix Oct 12 '18 at 18:17
  • @Phoenix `From` from a type `T` to itself already exists for any `T`, so you are not allowed to redefine that for `IntPair`. But `impl From> for IntPair` should suffice for what you want to do. – starblue Oct 12 '18 at 20:15
  • 1
    @Starblue that doesn't really fit my goal. MCVE aside, there may be a large number of element types which implement `Into`. I do not want to re-implement a conversion into `IntPair` each time. – Phoenix Oct 12 '18 at 21:58

0 Answers0