Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I implement std::convert::From vs std::convert::Into?

Tags:

rust

I see that std::convert::Into has an implementation for anything that implements std::convert::From:

impl<T, U> Into<U> for T where     U: From<T>,  

In the Rust 1.0 standard library, there are many implementations of From while Into is only implemented in 3 places. This makes it seem like implementing From should be the default. I'm certain that there are times I would want to implement Into and not From, but I'm not seeing them.

like image 529
Shepmaster Avatar asked Apr 23 '15 02:04

Shepmaster


People also ask

Should I implement from or into?

The opposite of From . One should avoid implementing Into and implement From instead. Implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.

What is Try_into Rust?

Trait std::convert::TryIntoAn attempted conversion that consumes self , which may or may not be expensive.

How do you implement a trait in Rust?

Implementing a trait in Rust To implement a trait, declare an impl block for the type you want to implement the trait for. The syntax is impl <trait> for <type> . You'll need to implement all the methods that don't have default implementations.

What is Rust trait?

A trait in Rust is a group of methods that are defined for a particular type. Traits are an abstract definition of shared behavior amongst different types. So, in a way, traits are to Rust what interfaces are to Java or abstract classes are to C++. A trait method is able to access other methods within that trait.


1 Answers

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 have From<[T]> for Vec<T> where T: Clone, which yields the corresponding Into 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 of Into

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.

like image 196
Levans Avatar answered Nov 10 '22 06:11

Levans