Un atelier Rust · Édition d'ApprentissageA Rust Workshop · Learning Edition

Result & l'opérateur ?, ou l'erreur comme valeur Result & the ? operator, or the error as a value

L'erreur est dans le type de retour, pas dans un canal parallèle invisible comme l'exception. La distinction qui structure tout : erreur attendue vs bug. The error lives in the return type, not in an invisible parallel channel like the exception. The distinction that structures everything: expected error vs bug.

AudienceAudience
Dev à l'aise avec enums et Option (Vol 3) Dev comfortable with enums and Option (Vol 3)
Format
Self-paced
ChapitresChapters
5
Date
Juin 2026 Jun 2026
≈ 18 min ●●○○ ErreursResult?

Chapitre 1 en accès libre — la suite (ch. 2 à 5) est réservée. Chapter 1 free to read — the rest (ch. 2–5) is members-only.

01CadrageFraming3 min

L'échec n'est pas une interruption surprise. C'est une valeur de retour.Failure isn't a surprise interruption. It's a return value.

Le Vol 3 a appris à rendre l'illégal impossible à écrire. Mais toutes les erreurs ne sont pas des bugs à proscrire : un fichier qui n'existe pas, un réseau qui tombe, une saisie invalide sont des événements normaux. La plupart des langages les signalent par une exception — un canal parallèle, invisible dans la signature, qui saute par-dessus ton code jusqu'à ce que quelqu'un l'attrape, ou pas. Rust prend le chemin inverse : l'échec est une valeur ordinaire, Result<T, E>, posée dans le type de retour. Le même enum que partout — Ok ou Err — au cœur de la gestion d'erreur la plus honnête qui soit.Vol 3 taught us to make the illegal impossible to write. But not every error is a bug to forbid: a file that isn't there, a network that drops, invalid input are normal events. Most languages signal them with an exception — a parallel channel, invisible in the signature, that leaps over your code until someone catches it, or doesn't. Rust takes the opposite path: failure is an ordinary value, Result<T, E>, placed in the return type. The same enum as everywhere — Ok or Err — at the heart of the most honest error handling there is.

Result — l'enum d'Option, mais l'échec porte sa raisonResult — Option's enum, but failure carries its reason
enum Result<T, E> {   // exactement la forme d'Option, mais l'absence porte une RAISON
    Ok(T),            // le succès, qui transporte la valeur attendue
    Err(E),           // l'échec, qui transporte ce qui a mal tourné
}

// lire un fichier peut échouer : le type de retour le DIT
fn lire_config(chemin: &str) -> Result<String, std::io::Error> { /* ... */ }

let config = lire_config("app.toml");   // config est Result<String, Error>
// impossible d'utiliser le String sans d'abord regarder le cas Err en face.
Attendue, ou bug ?Expected, or bug?

La question qui structure tout le volume : est-ce une erreur attendue, ou un bug ? Un fichier absent, un port occupé, un JSON malformé : ce sont des conditions du monde réel, prévisibles — elles appartiennent au type de retour, en Result. Un invariant qu'on s'était promis et qui se rompt (un index hors borne, un état qui ne devrait jamais arriver) : ça, c'est un bug, et ça relève du panic — le sujet du n°3. Confondre les deux est la première erreur de conception : on ne met pas un bug dans un Result, et on ne fait pas paniquer sur un fichier manquant.The question that structures the whole volume: is this an expected error, or a bug? A missing file, a busy port, malformed JSON: these are predictable real-world conditions — they belong in the return type, as Result. An invariant you promised yourself that breaks (an out-of-bounds index, a state that should never happen): that's a bug, and it's the realm of panic — issue n°3's subject. Confusing the two is the first design mistake: you don't put a bug in a Result, and you don't panic on a missing file.

Le réflexe du numéroThe issue's reflex

« Cette fonction peut-elle échouer pour une raison normale ? » Si oui, elle renvoie un Result, et le compilateur force l'appelant à traiter l'échec — exactement comme Option forçait à traiter l'absence. L'erreur cesse d'être une chose qui arrive à ton code pour devenir une chose qui est dans ton code, qu'on lit, transforme et propage.'Can this function fail for a normal reason?' If so, it returns a Result, and the compiler forces the caller to handle the failure — exactly as Option forced handling absence. The error stops being something that happens to your code and becomes something that is in your code, read, transformed and propagated.

Result, c'est Option avec un pourquoi.Result is Option with a why.

Option<T> dit « il y a une valeur, ou rien ». Result<T, E> dit « il y a une valeur, ou un échec — et voici lequel ». Là où None est muet, Err(e) transporte le diagnostic. Tout ce que tu as appris sur Option — match, if let, ?, les combinateurs — se transpose presque tel quel sur Result. C'est le même enum, enrichi d'une raison.Option<T> says 'there's a value, or nothing'. Result<T, E> says 'there's a value, or a failure — and here's which'. Where None is mute, Err(e) carries the diagnosis. Everything you learned about Option — match, if let, ?, the combinators — transfers almost unchanged to Result. It's the same enum, enriched with a reason.

🔒

La suite est réservée The rest is members-only

Le premier numéro est libre. Débloque tout The Rust Loop — tous les volumes, à vie — pour 5 €, paiement unique. The first issue is free. Unlock all of The Rust Loop — every volume, forever — for €5, one-time.

Retour au kiosqueBack to newsstand