dmyTRUEk
dmyTRUEk

Reputation: 57

How to implement `From` for `Either` in Rust

I have Either type:

enum Either<L, R> {
  Left(L),
  Right(R),
}

and i want to implement From trait for both of it's variants:

impl<L, R> From<L> for Either<L, R> {
    fn from(l: L) -> Self {
        Self::Left(l)
    }
}
impl<L, R> From<R> for Either<L, R> {
    fn from(r: R) -> Self {
        Self::Right(r)
    }
}

and yes, obviously they overlaps. So the question is how to make Either's L and R generic types not equal and implement both Froms? So that:

type EitherStringString = Either<String, String>; // compilation error, because `Either`'s `L` and `R` types are equal
type EitherStringInt = Either<String, i32>; // ok
#[test]
fn either_string_int_from_string() { // ok
  let string: String = String::from("hello");
  assert_eq!(
    Either::<String, i32>::Left(string),
    string.into()
  );
}
#[test]
fn either_string_int_from_int() { // ok
  let number: i32 = 42;
  assert_eq!(
    Either::<String, i32>::Right(number),
    number.into()
  );
}

"Prior art": negative_bounds and negative_impls features looks like this is the exact thing i need, but i can't figure out how to use them to achieve desired result. I tried:

#![feature(negative_bounds, negative_impls)]

trait LT {}
trait RT: !LT {}

// neither combination of this solves the issue
// impl<L: !RT> LT for L {}
// impl<L> !RT for L {}
// impl<R: !LT> RT for R {}
// impl<R> !LT for R {}

impl<L: LT, R: RT> From<L> for Either<L, R> {
    fn from(l: L) -> Self {
        Self::Left(l)
    }
}
impl<L: LT, R: RT> From<R> for Either<L, R> {
    fn from(r: R) -> Self {
        Self::Right(r)
    }
}

but this gives compilation error:

conflicting implementations of trait `From<_>` for type `either::Either<_, _>`

So how to implement From for Either?

Upvotes: 2

Views: 143

Answers (0)

Related Questions