Standard library offers a very convenient and natural implementation of From<T> for T
.
This implementation, however, sometimes creates problems for Rust developers who want to implement From
because of conflicting implementations.
One notable example of this is how anyhow::Error
cannot implement std::error::Error
.
Or, in general, if one wants to define a type-wrapper Wrapper<T>
and wants to permit reasonable behavior where Wrapper<T>
can be converted into Wrapper<U>
via From
/Into
as long as T
can be converted into U
, this is not possible either.
This is because the case of impl<T,U> From<Wrapper<T>> for Wrapper<U>
for T=U
is covered by the implementation from the standard library and Rust currently does not support specialization.
At the moment of writing, there's no way to to express that the implementation would apply only to T != U
.
Let's say I would like to implement such a bound in rustc
. Where would I be able to do this?
1 Like
After thinking for a while, I realize that it could also be the mechanism for having an autotrait-like behavior with a limited set of types-implementors.
You mean the From
implementation for impl<T, U: From<T>> From<Wrapper<T>> for Wrapper<U>
should carve out the T = U
case in order to have the (default) impl<W> From<W> for W
(for W = Wrapper<T> = Wrapper<U>
) apply there?
That sounds a lot like specialization and intuitively, I’d say such a T != U
-bounds feature – the way you’re imagining it (judging by your suggested use-cases) shares (at least in the general case) the same tricky-or-impossible-to-solve soundness problems.
3 Likes
I'm pretty sure this is equivalent to specialization in its troublesomeness, or even more so as it breaks lifetime erasure. Think about writing code like
struct Foo<'a> {...}
trait MyFrom<T> {...}
impl MyFrom<T> for T {...}
impl MyFrom<Foo<'static>> for T where T != Foo<'static> {...}
fn convert<'a>(input: Foo<'static>) -> Foo<'a> {
MyFrom::from(input)
}
Now convert
must be compiled to one of the two impls, depending on whether 'a
equals 'static
or not, and I didn't even write 'a != 'static
.
3 Likes
Technically this is specialization, but many impl<T,U> From<Wrapper<T>> for Wrapper<U>
has same logic (identity) with impl<T> From<T> for T
when T == U
. I wonder is there a way to permit this,