How to read this repetitive trait bound from combine crate?

I've been digging through the combine crate trying to figure out how I can retrieve useful parser errors for UI feedback when I stumbled across multiple trait bounds like this example.

impl<Input, X, E> Positioned for Stream<Input, X>
where
    Input: StreamOnce,
    X: Positioner<Input::Token>,
    E: StreamError<Input::Token, Input::Range>,
    Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = E>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = E>,
{
    #[inline]
    fn position(&self) -> Self::Position {
        self.positioner.position()
    }
}

The bit I find confusing are the two Input::Error trait bounds.

    Input::Error: ParseError<Input::Token, Input::Range, X::Position, StreamError = E>,
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position, StreamError = E>,

Is this declaring that X::Position and Input::Position must be the same type? If so, that's a verbose means of expressing a relationship.

No, it's just saying that the error must implement the same trait twice with different parameters.

It is possible for one type to implement the same trait for various different parameters simultaneously. For example String is both From<String> and From<&str>.

Of course, if X::Position and Input::Position are the same type, then that's fine too, but it's possible to satisfy the constraint without this being the case.

3 Likes