Conflicting implementations of trait `std::convert::Into<_>`

Hello,

I have the following code (Rust Playground):

use std::convert::{From,Into};

#[derive(Debug)]
pub struct Modulo<T>(T);

impl<T> From<T> for Modulo<T> {
        fn from(x: T) -> Self { Modulo(x) }
}

impl<T> Into<T> for Modulo<T> {
        fn into(self) -> T { self.0 }
}


#[cfg(test)]
mod tests {
        use super::*;

        #[test]
        fn modulo_new() {
                let x = Modulo(42);
                assert_eq!(42, x.into());
        }
}

And what I see when do cargo test is

error: conflicting implementations of trait `std::convert::Into<_>` for type `utils::Modulo<_>`: [E0119]

I wounder who could implement Into for my custom type? The error message says that it is core who has alternative implementation.
However, when I drop my Into implementation I see that no suitable Into implementation is found:

error: the trait bound `i32: std::convert::From<utils::Modulo<i32>>` is not satisfied [E0277]
             assert_eq!(42, x.into());

This is unfortunate. The problem is that you can't rely on the negative reasoning that T: !From<Modulo<T>>, since you don't control T or From. You need this because of the blanket impl of Into which otherwise applies. I'm not aware of any workarounds, except for writing impl Into<i32> for Modulo<i32> and repeating for each individual type. You could use a macro to generate the impls for you from a list of types. Maybe in the future the specialization rules will allow you to specialize the overlap in some way in order to remove the conflict. Under the specialization RFC as it stands, the impls would still conflict because neither is strictly more specific than the other and there's no way to resolve the conflict.

2 Likes

Yes, unfortunately you can't give an implementation of both traits this way as @stevenblenkinsop described.

In the standard library, a common pattern is to offer an into_inner function that does something like Into<T>. For your sample above, that could look like this.

1 Like