I'm trying to implement a generic TryFrom implementation to convert a pair of integers to a (potentially) narrower type. The basic code looks like this:
type ParsedComponent = i32;
type ParsedOffset = i32;
impl<'a, T, U> TryFrom<RawReferenceComponent<'a>> for ReferenceComponent<T, U>
where
T: TryFrom<ParsedComponent>,
<T as TryFrom<ParsedComponent>>::Error: Into<Error>,
U: TryFrom<ParsedOffset>,
<T as TryFrom<ParsedOffset>>::Error: Into<Error>
{
type Error = Error;
fn try_from(component: RawReferenceComponent<'a>) -> Result<Self> {
use self::RawReferenceComponent::*;
Ok(match component {
Index(index)
=> ReferenceComponent::Index(index.try_into()?),
ThisOffset(offset)
=> ReferenceComponent::ThisOffset(offset.try_into()?),
_ => unimplemented!(), // Omitted for brevity
})
}
}
However, I'm getting an error I don't understand:
error[E0277]: the trait bound `T: std::convert::From<i32>` is not satisfied
--> src/reference/relative.rs:122:1
|
122 | / impl<'a, T, U> TryFrom<RawReferenceComponent<'a>> for ReferenceComponent<T, U>
123 | | where
124 | | T: TryFrom<ParsedComponent>
125 | | <T as TryFrom<ParsedComponent>>::Error: Into<Error>,
... |
155 | | }
156 | | }
| |_^ the trait `std::convert::From<i32>` is not implemented for `T`
|
= help: consider adding a `where T: std::convert::From<i32>` bound
= note: required because of the requirements on the impl of `std::convert::TryFrom<i32>` for `T`
Why would I need a From bound on T in order to satisfy TryFrom? If I had such a thing, I wouldn't be bothering with TryFrom in the first place...
Here is a version that continues to use original code, more or less.
There’s no need for extra type parameters for the associated Error type - using normal projections works fine.
I think the issue is the compiler cannot see the link in T::Error: Into<Error>, but does understand the inverse Error: From<T::Error>. I find this a bit strange - presumably T::Error: Into<Self::Error> would be more convincing but this causes an overflow in requirement satisfying - not sure if that’s a bug or not.