# `From` and `Into` Let's go back to where our string journey started: ```rust let ticket = Ticket::new( "A title".into(), "A description".into(), "To-Do".into() ); ``` We now know enough to start unpacking what `.into()` is doing here. ## The problem This is the signature of the `new` method: ```rust impl Ticket { pub fn new( title: String, description: String, status: String ) -> Self { // [...] } } ``` We've also seen that string literals (such as `"A title"`) are of type `&str`.\ We have a type mismatch here: a `String` is expected, but we have a `&str`. No magical coercion will come to save us this time; we need **to perform a conversion**. ## `From` and `Into` The Rust standard library defines two traits for **infallible conversions**: `From` and `Into`, in the `std::convert` module. ```rust pub trait From: Sized { fn from(value: T) -> Self; } pub trait Into: Sized { fn into(self) -> T; } ``` These trait definitions showcase a few concepts that we haven't seen before: **supertraits** and **implicit trait bounds**. Let's unpack those first. ### Supertrait / Subtrait The `From: Sized` syntax implies that `From` is a **subtrait** of `Sized`: any type that implements `From` must also implement `Sized`. Alternatively, you could say that `Sized` is a **supertrait** of `From`. ### Implicit trait bounds Every time you have a generic type parameter, the compiler implicitly assumes that it's `Sized`. For example: ```rust pub struct Foo { inner: T, } ``` is actually equivalent to: ```rust pub struct Foo { inner: T, } ``` In the case of `From`, the trait definition is equivalent to: ```rust pub trait From: Sized { fn from(value: T) -> Self; } ``` In other words, _both_ `T` and the type implementing `From` must be `Sized`, even though the former bound is implicit. ### Negative trait bounds You can opt out of the implicit `Sized` bound with a **negative trait bound**: ```rust pub struct Foo { // ^^^^^^^ // This is a negative trait bound inner: T, } ``` This syntax reads as "`T` may or may not be `Sized`", and it allows you to bind `T` to a DST (e.g. `Foo`). It is a special case, though: negative trait bounds are exclusive to `Sized`, you can't use them with other traits. ## `&str` to `String` In [`std`'s documentation](https://doc.rust-lang.org/std/convert/trait.From.html#implementors) you can see which `std` types implement the `From` trait.\ You'll find that `String` implements `From<&str> for String`. Thus, we can write: ```rust let title = String::from("A title"); ``` We've been primarily using `.into()`, though.\ If you check out the [implementors of `Into`](https://doc.rust-lang.org/std/convert/trait.Into.html#implementors) you won't find `Into for &str`. What's going on? `From` and `Into` are **dual traits**.\ In particular, `Into` is implemented for any type that implements `From` using a **blanket implementation**: ```rust impl Into for T where U: From, { fn into(self) -> U { U::from(self) } } ``` If a type `U` implements `From`, then `Into for T` is automatically implemented. That's why we can write `let title = "A title".into();`. ## `.into()` Every time you see `.into()`, you're witnessing a conversion between types.\ What's the target type, though? In most cases, the target type is either: - Specified by the signature of a function/method (e.g. `Ticket::new` in our example above) - Specified in the variable declaration with a type annotation (e.g. `let title: String = "A title".into();`) `.into()` will work out of the box as long as the compiler can infer the target type from the context without ambiguity.