'What counts as a conflicting implementation?

In the following code:

enum Either<A, B> { Left(A), Right(B) }

use Either::{Left, Right};

impl<A, B> From<A> for Either<A, B> {
    fn from(a: A) -> Self {
        Left(a)
    }
}

impl<A, B> From<B> for Either<A, B> {
    fn from(b: B) -> Self {
        Right(b)
    }
}

I'm getting the following error: "conflicting implementations of trait std::convert::From<_> for type Either<_, _>". I do not understand how the implementation of From<A> and From<B> for Either<A, B> is conflicting.

I saw an example in the standard library docs where they're doing almost exactly what I'm doing but it works there:

use std::fs;
use std::io;
use std::num;

enum CliError {
    IoError(io::Error),
    ParseError(num::ParseIntError),
}

impl From<io::Error> for CliError {
    fn from(error: io::Error) -> Self {
        CliError::IoError(error)
    }
}

impl From<num::ParseIntError> for CliError {
    fn from(error: num::ParseIntError) -> Self {
        CliError::ParseError(error)
    }
}

Please can someone explain? Thanks.



Solution 1:[1]

In your original code:

enum Either<A, B> { Left(A), Right(B) }

use Either::{Left, Right};

impl<A, B> From<A> for Either<A, B> {
    fn from(a: A) -> Self {
        Left(a)
    }
}

impl<A, B> From<B> for Either<A, B> {
    fn from(b: B) -> Self {
        Right(b)
    }
}

You implement the From trait for Either<A, B> twice for From bound by the same traits A and B. Which is likely causing your issue where From is implemented multiple times. I cannot confirm that since the issue is not reproducible from the provided code. Using the code provided directly throws errors stating that A and B are undefined.

Combining the original and functional code together; we can provide definitions to the types. However, the following code will still fail due to improper bounding. In this case, the trait bounds are bound by a structure:

use std::{io, num};

enum Either<A, B> { Left(A), Right(B) }

use Either::{Left, Right};

impl<A: io::Error, B: num::ParseIntError> From<A> for Either<A, B> {
    fn from(a: A) -> Self {
        Left(a)
    }
}

impl<A: io::Error, B: num::ParseIntError> From<B> for Either<A, B> {
    fn from(b: B) -> Self {
        Right(b)
    }
}

Will result in the following error:

error[E0404]: expected trait, found struct `num::ParseIntError`

To make a functional version, the trait bounds should be removed. Resulting in something like the following which will compile without errors:

use std::{io, num};

enum Either<A, B> { Left(A), Right(B) }

type A = io::Error;
type B = num::ParseIntError;

use Either::{Left, Right};

impl From<A> for Either<A, B> {
    fn from(a: A) -> Self {
        Left(a)
    }
}

impl From<B> for Either<A, B> {
    fn from(b: B) -> Self {
        Right(b)
    }
}

From will only be usable on the type parameter it is implemented on and does not require the trait bounds.

You can find more information on trait bounds here: https://doc.rust-lang.org/reference/trait-bounds.html

You can find more information on type parameters here: https://doc.rust-lang.org/reference/types/parameters.html

You can find the documentation for the From trait here: https://doc.rust-lang.org/std/convert/trait.From.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1