From/Into & TryFrom
Implement From and TryFrom for explicit, discoverable conversions between types. Prefer these over ad-hoc as casts and constructor naming soup.
Search across all documentation pages
Implement From and TryFrom for explicit, discoverable conversions between types. Prefer these over ad-hoc as casts and constructor naming soup.
impl From<u64> for UserId {
fn from(id: u64) -> Self { UserId(id) }
}
let id: UserId = 42.into();
impl TryFrom<String> for Email {
type Error = ParseError;
fn try_from(s: String) -> Result<Self, Self::Error> { Email::parse(s) }
}When to reach for this: Boundary conversions, newtypes, parsing external input.
struct Meters(f64);
struct Feet(f64);
impl From<Feet> for Meters {
fn from(f: Feet) -> Self { Meters(f.0 * 0.3048) }
}
impl TryFrom<&str> for UserId {
type Error = std::num::ParseIntError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Ok(UserId(s.parse()?))
}
}What this demonstrates:
Into auto-implemented when From existsTryFrom + ?From over into_foo methodsImplement From on destination type. Chain with ? in handlers: let id = UserId::try_from(path_segment)?;. Avoid From that can fail; use TryFrom instead.
From; use TryFrom for validation.impl From<Foreign> for Foreign. Fix: newtype wrapper.UserId::from(x).TryFrom<u8> for wire formats.| Alternative | Use When | Don't Use When |
|---|---|---|
parse() inherent | single type string parse | cross-type standard trait |
as primitive cast | numeric widening rules clear | domain validation |
map on Option | light transform | public API conversion |
new for domain semantics; TryFrom when converting from external representation.
Deserialize to DTO then TryInto domain type in handler.
Avoid conflicting impls; follow orphan rules.
fn f<T: Into<UserId>>(t: T) accepts many sources.
Use domain error enum, not String.
TryFrom<&str> common; owned TryFrom<String> avoids extra alloc when already owned.
Prefer TryFrom over as for user input.
assert_eq!(x, T::from(U::from(x))) when bijection holds.
Newtype then From/TryFrom on newtype.
Rustdoc examples showing from, into, try_from.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026