Gestion des erreurs
Le type Result est la façon privilégiée en Rust pour décrire le type de retour
des fonctions dont le traitement peut échouer. Un objet Result doit être
testé et jamais ignoré.
Une crate PEUT implanter son propre type Error qui peut contenir toutes
les erreurs possibles. Des précautions supplémentaires DOIVENT être prises :
ce type DOIT être exception-safe (RFC 1236) et implémenter les traits
Error + Send + Sync + 'static ainsi que Display.
Des crates tierces peuvent être utilisées pour faciliter la gestion d'erreurs. La plupart (snafu, thiserror) proposent la création de types d'erreurs personnalisées qui implémentent les traits nécessaires et permettent l'encapsulation d'autres erreurs.
Une autre approche (notamment proposée dans anyhow) consiste à envelopper automatiquement les erreurs dans un seul type d'erreur universel. Une telle approche ne devrait pas être utilisée dans des bibliothèques ou des systèmes complexes parce qu'elle ne permet pas de fournir de contexte sur les erreurs ainsi initialement enveloppées, contrairement à la première approche.
Panics
Dans le cas général, la gestion explicite des erreurs (Result) doit être préférée à la place de
l'utilisation de la macro panic. La cause de l'erreur doit être rendue
disponible, et les erreurs trop génériques doivent être évitées.
Une fonction Rust NE PEUT émettre de panic QUE lorsque les conditions de son usage ont été violées.
Les crates fournissant des bibliothèques ne doivent pas utiliser de fonctions
ou d'instructions qui peuvent échouer en engendrant un panic.
Les motifs de code suivants provoquent explicitement des panic :
- une utilisation de
unwrapou deexpect; - une utilisation de
assert!.
De la règle précédente découle la règle suivante.
Les usages de unwrap, expect et de assert! DOIVENT être restreints aux seuls cas interdits par la spécification de la fonction.
Les fonctions suivantes sont connues pour émettre des panic en cas d'arguments ne respectant pas les conditions d'usage.
- un accès non vérifié à un tableau (voir la recommendation suivante) ;
- un dépassement d'entier (en mode debug, voir le chapitre sur le traitement des entiers) ;
- une division par zéro ;
- allocation importante de mémoire ;
- l'utilisation de
format!pour le formatage d'une chaîne de caractères.
L'indice d'accès à un tableau DOIT être testé, ou la méthode get DOIT être
utilisée pour récupérer un type Option.
Dans certains domaines critiques pour la sureté, il est obligatoire de passer en mode sans échec dès qu'une erreur susceptible d'entraîner un comportement indéfini se produit. Dans ces situations, il est judicieux d'interrompre l'exécution puisque cela permet d'arrêter le système avant que des données ne soient corrompues, ou des défaillances liées à la sûreté ne se propagent.
Pour un avion ou d'autres types de véhicule, ce comportement « fail-fast » peut être crucial : l'unité de contrôle principale doit s'arrêter immédiatement en cas de défaillance grave, puis transférer le contrôle à un sous-système redondant ou de secours capable d'arrêter le véhicule en toute sécurité ou de poursuivre son fonctionnement en mode réduit. Le redémarrage sur un système secondaire fiable garantit que le véhicule reste contrôlable, protège les occupants et évite les conséquences dangereuses qui pourraient résulter de la poursuite de l'exécution dans un état imprévisible.
Pour ce cas d'usage, activer l'attribut panic = 'abort' dans la section [profile.release] du fichier Cargo.toml permet d'arrêter le programme dès l'émission du panic.
FFI et panics
L'intégration d'autres langages en Rust passe par une FFI (Foreign Function Interface). Cette fonctionnalité est décrite plus en détails dans le chapitre dédié.
Références
- Recover (RFC-1236)