When should I implement std::convert::From vs std::convert::Into?
Solution 1:
TL;DR: prefer implementing From
.
Interestingly, the original RFC about the std::convert
traits suggested the opposite blanket implementation:
impl<T, U> From<T> for U
where
T: Into<U>
But on the PR implementing it, it was changed to the opposite:
Added
From
=>Into
implementation, which makes it possible to add conversions in both directions without running afoul of coherence. For example, we now haveFrom<[T]> for Vec<T>
whereT: Clone
, which yields the correspondingInto
going in the other direction -- despite the fact that the two types live in different crates.I also believe this addresses a few concerns about things implementing
From
instead ofInto
This last-moment change reflects that From
and Into
are basically equivalent. From
was chosen as the preferred one as it was less restrictive from the "type parameter vs. local type" point of view.
Before Rust 1.41.0, it wasn't possible to make a impl<'a, T> Into<Foo> for &'a [T]
, while impl<'a, T> From<&'a [T]> for Foo
was possible.
The first attempt raised a E0210
:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> x.rs:3:10
|
3 | impl<'a, T> Into<Foo> for &'a [T] {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
In the standard library prior to Rust 1.14, there were only two examples of implementing Into
and not From
:
impl Into<Vec<u8>> for String
impl Into<OsString> for PathBuf
I think these are the reflexion of the logic of their interfaces. OsString
implements From<String>
and From<T> where T: AsRef<OsStr>
, because they are the natural things you'll want to build a OsString
from.
However, PathBuf
still implements Into<OsString>
as the reverse operation of its From<OsString>
implementation, but this logic belongs to PathBuf
, not OsString
.