I'm currently writing a parsing library that should allow for generic parsing of, for example, binary files, a series of tokens, or a character string. Therefore I defined two traits:
trait Supplier {
type Item: Clone;
type Error: Debug;
/// get the current item, without advancing
fn current(&mut self) -> Result<Option<Self::Item>, Self::Error>;
/// step the supplier, either forward or backwards
fn step(&mut self, steps: i64) -> Result<(), Self::Error>;
// … more functions with default implementations
}
trait Parseable<Item> {
type Output;
/// parse Self from a given [`Supplier`]
fn parse<S: Supplier<Item = Item>>(supplier: &mut S) -> Result<Self::Output, S::Error>;
}
A type that can supplier some items implements the Supplier
trait.
For example, a binary file would implement Supplier<Item = u8>
, a text-file Supplier<Item = char>
and a tokenizer/scanner/lexer Supplier<Item = Token>
.
A type that can be parsed from a stream of items implements Parseable<Item>
with Item
being the type of items in the stream it can be parsed from.
For example, a usize would implement Parseable<u8>
and an expression (when thinking about a programming language or maths expression) implements Parseable<Token>
for some type Token
.
I need the Parseable::Output
to be an associated type in order to allow types to fail parsing using a Result<Self, /* some error type */>
as output.
I then want to write some (generic) implementations for existing types, one of which is a Vec<T>
.
Here the following problem arises:
In case T::Output
is a Result<T, /* some error type */
, I want to return a Result<Vec<T>, T::Error>
(the error of course in case one parse of T
fails).
In the case that T::Output
is T
itself, i.e. its parse is infallible, the return type should be Vec<T>
directly.
I hope it's clear what I want to do.
I've tried the following set of implementations:
impl<Item, T, Error> Parseable<Item> for Vec<T>
where
T: Parseable<Item, Output = Result<T, Error>>,
usize: Parseable<Item>,
{
type Output = Result<Self, Error>;
fn parse<…>(…) -> … { … }
}
impl<Item, T> Parseable<Item> for Vec<T>
where
T: Parseable<Item, Output = T>,
usize: Parseable<Item>,
{
type Output = Self;
fn parse<…>(…) -> … { … }
}
The compiler shows an error E0119 (conflicting implementations of trait Parseable<_>
for type Vec<_>
).
I kind of see why the compiler sees two conflicting implementations, but don't quite understand why exactly they are conflicting.
And, in case it exists, what is the correct / idiomatic way of implementing this?
Associated types are designed to allow only one implementation. So you don't want an associated type, you want a plain generic.