Reputation: 955
In this following code snippet, convert
is trying to convert its input to a Box<Error>
:
fn convert<T: Into<Box<Error>>>(input: T) -> Box<Error> {
input.into() // Compiles
// From::from(input) // Fails to compile
}
It works with input.into()
, but when using From::from(T)
it no longer works, it requires T
to implement Error
:
error[E0277]: the trait bound `T: std::error::Error` is not satisfied
--> src/main.rs:4:3
|
4 | From::from(input)
| ^^^^^^^^^^ the trait `std::error::Error` is not implemented for `T`
|
= help: consider adding a `where T: std::error::Error` bound
= note: required because of the requirements on the impl of `std::convert::From<T>` for `std::boxed::Box<std::error::Error>`
= note: required by `std::convert::From::from`
Why do the requirements change when using From
or Into
? This becomes specially annoying when using the ?
operator:
fn convert<T: Into<Box<Error>>>(input: T) -> Result<(), Box<Error>> {
Err(input)? // Fails to compile
}
Is there any way to use the ?
operator properly in these cases, or do I have to resort to manual match
and into
?
Upvotes: 3
Views: 191
Reputation: 430634
Why do the requirements change when using
From
orInto
?
Even when something implements Into
, that doesn't mean it implements From
. For example, from the implementor list of Into
:
impl<T, U> Into<U> for T
where
U: From<T>,
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData
impl Into<Vec<Annotatable>> for Annotatable
impl<T> Into<Vec<T>> for ThinVec<T>
impl<T> Into<Vec<T>> for P<[T]>
Those last four types do not implement From
, but they do implement Into
. (Note that these types are actually internal compiler types and it's a bug that we can see them in the docs, but it's a useful demonstration for this case.)
See When should I implement std::convert::From vs std::convert::Into? for more details about the differences of the two traits.
You can instead declare that your generic type implements From
to use it:
fn convert<T>(input: T) -> Box<Error>
where
Box<Error>: From<T>,
{
From::from(input) // Fails to compile
}
Upvotes: 9
Reputation: 19416
One solution would be to write your generics in terms of From
:
fn convert<T>(input: T) -> Result<(), Box<Error>>
where
Box<Error>: From<T>,
{
Err(input)?
}
Upvotes: 4