Is there a way to express the concept of `Dual` which also uses the `std::convert::{From, Into}` traits?

Is there a way to express the concept of Dual which also uses the std::convert::{From, Into} traits?

Example:

/*
[dependencies]

*/
use std::convert::From;

struct Call;
struct Put;

trait Dual {
    type Dual;

    fn dual(self) -> Self::Dual;
}

impl Dual for Call {
    type Dual = Put;

    fn dual(self) -> Put {
        Put
    }
}

impl Dual for Put {
    type Dual = Call;

    fn dual(self) -> Call {
        Call
    }
}

impl<T: Dual<Dual = T>> From<<T as Dual>::Dual> for T {
    fn from(self) -> Self {
        self.dual().into()
    }
}

fn main() {}

Playground

In the above codes, I want to express the idea that only Call can be converted into Put because Call is Dual to Put into the definition of the from method of the From trait. I also want to express that only any type T: Dual that implements Dual can be converted 'from' another that implements Dual<Dual = T> trait.

However, this is the error that I got:

Compiling playground v0.0.1 (/playground)
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
  --> src/main.rs:32:6
   |
32 | impl<T: Dual<Dual = T>> From<<T as Dual>::Dual> for T {
   |      ^ type parameter `T` must be used as the type parameter for some local type
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
   = note: only traits defined in the current crate can be implemented for a type parameter

For more information about this error, try `rustc --explain E0210`.
error: could not compile `playground` (bin "playground") due to 1 previous error

This is a “blanket implementation”, because it is implementing a trait for T (with some bounds, but the bounds don't matter). As a general rule, you only get to write a blanket implementation if the trait is defined in your own crate, because it can conflict with other impls that other crates might want to write.

1 Like

Does that mean the only way to actually enable such a feature is to create a new trait that my crate owns?

Thank you

I don't know that I understand everything you want, but you can do this.

trait Dual: Sized {
    type Dual: Dual<Dual = Self>;
    fn dual(self) -> Self::Dual;
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.