Skip to content

Conversion

One line: Four ways to turn one type into another, where the only decision that matters is whether the conversion is allowed to fail — plus a fifth you never write, which the compiler performs for you at a fixed list of places.

cannot fail      From / Into        u64::from(n)        n.into()
can fail         TryFrom / TryInto  u8::try_from(n)?    n.try_into()?
from text        FromStr            "4".parse::<T>()?
no check at all  as                 n as u8
never written    coercion           width(&owned)       &String -> &str

The first three are traits, so they are extensible, greppable, and visible in a signature. The fourth is built into the language, never fails, and loses data in four different ways without saying so. The fifth is not something you do at all — it is the compiler adjusting a reference's type where it already knows what it wants, and the list of adjustments it will make is short and closed.

Lesson Level What it covers
From and Into 201 Write one, get both — and why ? converts your errors for free
TryFrom and TryInto 201 The same shape plus a type Error, and FromStr for the text case
Casting with as 201 Truncation, sign reinterpretation, saturation and rounding, all silent
Coercion: the conversion you never write 201 The fifth one, and the only implicit one — where it fires, the closed list of what it will do, and the three places it will not help you

The one table

You are doing Write
widening an integer, or any conversion that cannot fail u64::from(n)
narrowing, or anything with an invalid input u8::try_from(n)?
turning text into a value s.parse::<T>()?
truncating on purpose n as u8, with a comment

Where the rest of it is

Text conversion in both directions has its own section: parsing out of a string going in, and Display coming back out — implement Display and ToString arrives free, exactly the way Into arrives free from From. ToOwned is the fourth conversion trait, for the borrowed-to-owned case where the owned twin is a different type (&strString).

Where it goes next

Every one of these is a trait with a blanket impl behind it, which is what a trait is at its most useful. And the reason try_from returns something you have to open is Option and Result.

Po polsku

Konwersja typów (conversion) rozkłada się w Ruscie na cztery drogi, a wybiera między nimi jedno pytanie: czy konwersja ma prawo się nie udać. Nie może — From/Into, czyli u64::from(n); może — TryFrom/TryInto, czyli u8::try_from(n)?; z tekstu — FromStr wywoływany przez "4".parse::<T>()?; a n as u8 to rzutowanie bez żadnego sprawdzenia. Kto przychodzi z C, Javy czy ABAP-a, sięgnie po as odruchowo, bo tam rzutowanie jest zwykłą drogą konwersji — w Ruscie to wyjątek, który po cichu gubi dane na cztery różne sposoby, podczas gdy pozostałe trzy drogi to cechy (traits): rozszerzalne, widoczne w sygnaturze funkcji i możliwe do znalezienia grepem.

Piąta droga to koercja, której się nie pisze: kompilator sam dopasowuje typ referencji w kilku ściśle wyliczonych miejscach — dlatego width(&owned) działa, mimo że &owned to &String, a funkcja chce &str. Lista tych dopasowań jest zamknięta i nie ma na niej żadnej konwersji liczbowej.

Szukaj po polsku: konwersja typów w Ruscie · rzutowanie typów · koercja · rust From Into trait · rust TryFrom · rust as cast truncation · rust deref coercion