Rust From & Into
From and Into are a pair of traits that convert one type into another. String::from("hello") turns a text view into owned text.
From says how to build the new value
impl From<Old> for New says how to build a New value from an Old one.
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}Call it as Type::from
Type::from(value) runs the conversion.
let num = Number::from(30);
println!("{:?}", num);Into reads the same conversion the other way
Implement From and you get Into for free. The standard library writes the Into side for you. It writes it from your From code.
let num2: Number = 5.into();
println!("{:?}", num2);The library converts too
The standard library already converts many pairs this way: a &str into a String, an i32 into an i64.
let text = String::from("hello");
let wide: i64 = 7i32.into();
println!("{} {}", text, wide);Example
#[derive(Debug)]
struct Number { value: i32 }
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let text = String::from("hello");
let num = Number::from(30);
let num2: Number = 5.into();
let wide: i64 = 7i32.into();
println!("{} {:?} {:?} {}", text, num, num2, wide);
}Key points
- The reverse is not true: writing only Into does not give you From — so always implement From
- Use .into() with the target type written down, like let n: Number = 5.Add into(); to name the target.
- Without it, Rust cannot guess the target.
- It stops with error E0283
- A From conversion is expected never to fail: if a conversion can fail, use TryFrom instead — the next lesson
- Use From and Into for a meaningful change between types, especially your own types.
- From and Into move a value from one type to another by conversion.
In this example, the impl block teaches Number a skill. It teaches it how to build itself from an i32. It stores the number in the value field. In main, String::from("hello") uses a conversion the standard library wrote, and Number::from(30) uses ours. The next line runs the very same conversion the other way: 5.into() becomes a Number, because the annotation Number tells Rust the target type. The last conversion is also from the standard library: an i32 widens into an i64. All four values print on one line.
Note
Use as for a quick cast between primitive numbers.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
You implement From<i32> for your own type Number. What else do you get for free?