0

I'm trying to define a generic From implementation for a struct like this (playground):

struct Wrapped<T: Clone>(T);

impl<T: Clone, __Into0: ::std::convert::Into<T>> ::std::convert::From<(__Into0)> for Wrapped<T> {
    fn from(original: (__Into0)) -> Wrapped<T> {
        Wrapped(original.into())
    }
}

fn main() {
    let _: Wrapped<i64> = 5i32.into();
} 

However, I get the following error:

error[E0119]: conflicting implementations of trait `std::convert::From<Wrapped<_>>` for type `Wrapped<_>`:
 --> src/main.rs:3:1
  |
3 | / impl<T: Clone, __Into0: ::std::convert::Into<T>> ::std::convert::From<(__Into0)> for Wrapped<T> {
4 | |     fn from(original: (__Into0)) -> Wrapped<T> {
5 | |         Wrapped(original.into())
6 | |     }
7 | | }
  | |_^
  |
  = note: conflicting implementation in crate `core`

I'm guessing this is caused by the fact that From is implemented for every type to itself and my new implementation also includes a way to solve that because of that.

I'm not sure how to solve this recursion-like behaviour. The only solution I can think of is to use a single element tuple instead (playground):

struct Wrapped<T: Clone>(T);

impl<T: Clone, __Into0: ::std::convert::Into<T>> ::std::convert::From<(__Into0,)> for Wrapped<T> {
    fn from(original: (__Into0,)) -> Wrapped<T> {
        Wrapped(original.0.into())
    }
}

fn main() {
    let _: Wrapped<i64> = (5i32,).into();
}

This works, but it makes the API more awkward than I would like. Are there any other ways to solve this compilation error?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
JelteF
  • 3,021
  • 2
  • 27
  • 35
  • Stylistic points: (1) Don't use leading underscores for identifiers that are used (e.g. `__Into0`); they are semantically reserved for identifiers that need to exist but are unused. (2) `From` and `Into` are imported via the *prelude*, so you don't need to fully qualify them. (3) There's no reason to have the parenthesis on your non-tuple version. (4) Consider using a `where` clause as soon as you have any non-trivial bounds. [complete example](https://play.rust-lang.org/?gist=6b6b20bdae25237edf5b2c32c32791ee&version=stable). – Shepmaster Sep 24 '17 at 01:02
  • I'd encourage you to post your workaround as an answer on the linked duplicate. – Shepmaster Sep 24 '17 at 01:13
  • Thanks for the stylistic comments, but this code is generated by a custom derive so it's a bit less important there. And I'll share my workaround on the duplicate. – JelteF Sep 25 '17 at 08:20

0 Answers0