Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. From / Into / TryFrom / TryInto Traits

From / Into / TryFrom / TryInto Traits

Rust's type conversion traits — From, Into, TryFrom, and TryInto — standardize conversions between types. Implementing From automatically provides Into as well.

Syntax

use std::convert::TryFrom;

// Implementing the From trait.
struct Wrapper(i32);

impl From<i32> for Wrapper {
    fn from(val: i32) -> Self {
        Wrapper(val)
    }
}

// Implementing From automatically enables Into as well.
let w: Wrapper = Wrapper::from(42);     // Using From.
let w: Wrapper = 42.into();             // Using Into (type annotation specifies the target type).

// TryFrom: a fallible conversion that returns a Result.
impl TryFrom<i32> for Wrapper {
    type Error = String;

    fn try_from(val: i32) -> Result<Self, Self::Error> {
        if val >= 0 {
            Ok(Wrapper(val))
        } else {
            Err(format!("Negative values are not accepted: {}", val))
        }
    }
}

Conversion Traits

TraitDescription
From<T>Converts from another type T into the implementing type (infallible conversion).
Into<U>Converts the implementing type into another type U (automatically implemented when From<Self> for U is implemented).
TryFrom<T>Attempts to convert from another type T into the implementing type, returning Result<Self, Error>.
TryInto<U>Attempts to convert the implementing type into another type U (the counterpart of TryFrom).
AsRef<T>Provides a conversion from the implementing type to &T (a zero-cost reference conversion).
AsMut<T>Provides a conversion from the implementing type to &mut T.

Sample Code

use std::convert::TryFrom;

#[derive(Debug)]
struct Celsius(f64);

#[derive(Debug)]
struct Fahrenheit(f64);

// Converting from Fahrenheit to Celsius.
impl From<Fahrenheit> for Celsius {
    fn from(f: Fahrenheit) -> Self {
        Celsius((f.0 - 32.0) * 5.0 / 9.0)
    }
}

// Converting from Celsius to Fahrenheit.
impl From<Celsius> for Fahrenheit {
    fn from(c: Celsius) -> Self {
        Fahrenheit(c.0 * 9.0 / 5.0 + 32.0)
    }
}

// A newtype pattern with a constrained value range.
#[derive(Debug)]
struct Percentage(f64);

impl TryFrom<f64> for Percentage {
    type Error = String;

    fn try_from(value: f64) -> Result<Self, Self::Error> {
        if (0.0..=100.0).contains(&value) {
            Ok(Percentage(value))
        } else {
            Err(format!("Percentage must be between 0 and 100. Got: {}", value))
        }
    }
}

fn main() {
    // Using From / Into.
    let boiling_f = Fahrenheit(212.0);
    let boiling_c = Celsius::from(boiling_f);
    println!("212°F = {:.1}°C", boiling_c.0);

    let freezing_c = Celsius(0.0);
    let freezing_f: Fahrenheit = freezing_c.into();  // Using Into.
    println!("0°C = {:.1}°F", freezing_f.0);

    // Examples of From / Into from the standard library.
    let s = String::from("hello");      // From<&str> for String
    let s2: String = "world".into();    // Into<String> for &str
    println!("{}, {}", s, s2);

    let n: i64 = 42_i32.into();  // Safe conversion from i32 to i64.
    println!("i32 -> i64: {}", n);

    // Using TryFrom.
    let good = Percentage::try_from(75.0);
    let bad = Percentage::try_from(150.0);
    println!("75.0 -> {:?}", good);   // Ok(Percentage(75.0))
    println!("150.0 -> {:?}", bad);   // Err(...)

    // TryInto works the same way (requires use std::convert::TryInto).
    use std::convert::TryInto;
    let result: Result<Percentage, _> = 50.0_f64.try_into();
    println!("50.0 try_into: {:?}", result);

    // From/Into example with strings.
    let num: i32 = 42;
    let s = num.to_string();  // ToString is auto-implemented via Display
    let back: i32 = s.parse().unwrap();
    println!("i32 -> String -> i32: {}", back);
}

Notes

Implementing From automatically provides Into. This is known as Rust's "From/Into duality" — you only need to implement From, and Into is derived for free.

When writing function parameters, accepting Into frees callers from having to convert manually. For example, fn new(name: impl Into<String>) accepts both &str and String, making the function more flexible.

For the basics of trait definitions, see trait / impl Trait for Type.

If you find any errors or copyright issues, please .