Toutes les erreurs ne se gèrent pas. Certaines doivent tout arrêter.Not every error is to be handled. Some must stop everything.
Deux numéros ont martelé : ne panique pas, propage. On pourrait en conclure qu'un programme bien écrit ne panique jamais — ce serait l'erreur inverse du unwrap partout, mais une erreur quand même. La distinction qui ouvrait le volume revient ici pour le clore : une erreur attendue (fichier absent, réseau coupé, saisie invalide) appartient au Result ; un bug — un invariant qu'on s'était promis et qui se rompt — n'a rien à y faire. Quand un état déclaré impossible survient, continuer en faisant semblant est pire que s'arrêter : on propagerait des données corrompues. Là, paniquer n'est pas un échec de conception, c'est la conception.Two issues hammered: don't panic, propagate. You might conclude a well-written program never panics — that would be the mirror of unwrap-everywhere, but a mistake all the same. The distinction that opened the volume returns to close it: an expected error (missing file, dropped network, invalid input) belongs in a Result; a bug — an invariant you promised yourself that breaks — has no place there. When a state declared impossible occurs, carrying on pretending is worse than stopping: you'd propagate corrupted data. There, panicking isn't a design failure, it's the design.
// ERREUR ATTENDUE — le monde réel, prévisible → Result fn lire(chemin: &str) -> Result<String, io::Error> { /* le fichier peut manquer */ } // BUG — un invariant que MON code s'était promis → panic fn moyenne(notes: &[f64]) -> f64 { assert!(!notes.is_empty(), "moyenne() appelée sur une tranche vide"); notes.iter().sum::<f64>() / notes.len() as f64 // len() == 0 serait une faute } // la frontière : « le monde extérieur peut-il produire ça normalement ? » // oui → Result. non, c'est MA promesse qui se rompt → panic.
Un panic! déroule la pile (les destructeurs s'exécutent, la mémoire est libérée proprement) puis termine le thread — et, par défaut, le programme. Ce n'est pas un crash sauvage à la « segfault » : c'est un arrêt contrôlé, avec un message et, en debug, une trace. Tout l'enjeu est où on le déclenche. Paniquer au plus près de l'invariant rompu, c'est attraper le bug à sa source, avant qu'il ne contamine le reste. Le masquer en Result et le propager, c'est laisser le programme avancer sur une donnée déjà fausse — l'arrêt n'arrivera que plus loin, là où la cause est devenue illisible.A panic! unwinds the stack (destructors run, memory is freed cleanly) then ends the thread — and, by default, the program. It's not a wild 'segfault'-style crash: it's a controlled stop, with a message and, in debug, a trace. The whole question is where you trigger it. Panicking as close as possible to the broken invariant catches the bug at its source, before it contaminates the rest. Masking it as a Result and propagating it lets the program move on with already-wrong data — the stop comes only later, where the cause has become unreadable.
« Si cette condition survient, est-ce une situation que le monde produit normalement, ou la preuve que mon code a un bug ? » Normale → Result, on la gère. Bug → panic / assert, on s'arrête. Le critère n'est pas la gravité, mais l'origine : un disque plein est grave et reste un Result ; un index négatif est « anodin » et reste un bug.'If this condition arises, is it a situation the world produces normally, or proof my code has a bug?' Normal → Result, handle it. Bug → panic / assert, stop. The criterion isn't severity, but origin: a full disk is severe and stays a Result; a negative index is 'trivial' and stays a bug.
« Cette tranche n'est jamais vide ici », « cet index est toujours valide », « on n'atteint jamais cette branche ». Ce sont des promesses que ton code se fait à lui-même, qu'aucune entrée externe ne peut violer si le code est correct. Les rompre signifie donc une seule chose : le code est faux. Paniquer y est la réponse honnête — mieux vaut un arrêt net qu'un programme qui continue sur une hypothèse déjà fausse.'This slice is never empty here', 'this index is always valid', 'we never reach this branch'. These are promises your code makes to itself, that no external input can violate if the code is correct. Breaking them therefore means one thing: the code is wrong. Panicking is the honest answer — a clean stop beats a program running on an already-false assumption.