Problem in traits because of conflicting implementations

Hello,
I have a trait that is used to parse tree:

pub trait FromPairs {

    fn parse(pairs: Pairs<'_, Rule>) -> Result<Self,Error>;

}

impl <T: FromStr> FromPairs for T {
    fn parse(mut pairs: Pairs<'_, Rule>) -> Result<Self, Error> {
        pairs.get_str().parse()
    }
}

impl <T: FromPairs> FromPairs for Vec<T> {
    fn parse(mut pairs: Pairs<'_, Rule>) -> Result<Self, Error> {
        pairs.map(|x| x.into_inner().parse()).collect()
    }
}

And I get the following error:


I would like to have only one trait and no need for a Wrapper around Vec.
Is this possible?

Thanks for reading.
ccgauche.

1 Like

The reason the compiler doesn't like this is because there's no guarantee Vec<T> won't implement FromStr at some point in the future (you have no control over the standard library), and if that happened you wouldn't know which impl to use.

There's an unstable feature called specialization which tries to relax those rules when it is provable that one blanket implementation is strictly more specific than another, but that wouldn't work here because there's no "stricter than" relation ship between T: FromStr and Vec<T> where T: FromPairs.

Often you can work around these sorts of overlapping impl rules by introducing another level of indirection (i.e. an intermediate trait). Kinda like how we have the FromIterator trait because a direct impl<I, T> From<I> for Vec<T> where I: Iterator<T> would overlap with Vec's other From impls.

To X-Y your question, does your code ever use the FromPairs trait as part of a generic function or are they all concrete uses of the type implementing FromPairs? If the latter, you could be running into the Concrete Abstraction code and would gain a lot of clarity by dropping the FromPairs trait altogether and using normal functions/methods.

1 Like

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.