📖 Manuel
Rust Guide
Workflow
- Ownership et borrowing : Comprendre les trois règles d'ownership (une valeur = un owner, drop à la fin du scope, move sémantique), distinguer move (transfert) de clone (copie profonde), utiliser les références partagées
&T(lecture seule, multiples) et exclusives&mut T(une seule), respecter les règles d'emprunt pour éviter les data races à la compilation.
- Lifetimes : Comprendre que les lifetimes annotent les relations entre références (ne créent pas de durée de vie), appliquer l'élision de lifetime pour les cas simples, annoter explicitement quand le compilateur ne peut pas inférer (
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str), utiliser'staticuniquement pour les données vivant toute la durée du programme, placer les lifetimes dans les structs contenant des références.
- Error handling : Utiliser
Result<T, E>pour les erreurs récupérables,Option<T>pour les valeurs absentes, l'opérateur?pour propager les erreurs élégamment, créer des erreurs custom avecthiserror(#[derive(Error)]), utiliseranyhowpour les applications (context riche),thiserrorpour les bibliothèques (API publique stable).
- Traits et generics : Définir des comportements abstraits avec les traits (
trait Display { fn fmt(...) }), appliquer des trait bounds (fn print<T: Display>(val: T)), utiliserimpl Traiten paramètre/retour pour la concision,dyn Traitpour le dispatch dynamique (runtime), les associated types pour les traits avec un seul type lié (type Item), les blanket implementations pour étendre des types tiers.
- Patterns courants : Builder pattern avec méthodes chaînées et validation finale, newtype pattern (
struct Meters(f64)) pour la type safety, typestate pattern pour les machines à état vérifiées à la compilation (struct Connection<S: State>), enum-based state machines pour la logique métier, le patternFrom/Intopour les conversions idiomatiques.
- Async Rust : Utiliser
tokiocomme runtime async principal (#[tokio::main]), comprendre que lesFuturesont paresseux (ne s'exécutent que si pollés), écrire des fonctionsasync fnet lesawait, utilisertokio::spawnpour les tâches concurrentes,tokio::select!pour les races, les streams pour les séquences asynchrones, comprendre le pinning (Pin<Box<dyn Future>>) pour les self-referential types.
- Unsafe et FFI : Utiliser
unsafeuniquement quand les invariants sont vérifiés manuellement (raw pointers, appel FFI, implémentation de traits unsafe), documenter les invariants avec// SAFETY:comments, interagir avec C viaextern "C"et#[no_mangle], utiliserbindgenpour générer les bindings automatiquement, éviterstd::mem::transmutesauf si absolument nécessaire avec justification.
- Écosystème Cargo : Gérer les dépendances avec
Cargo.toml(features, workspace), utilisercargo clippypour les lints idiomatiques,cargo fmtpour le formatage,cargo testpour les tests intégrés,cargo benchpour les benchmarks (criterion.rs), les crates essentielles :serde/serde_json(sérialisation),clap(CLI),axum/actix-web(web),tokio(async runtime),rayon(parallélisme).
Règles
- Faire confiance au borrow checker : si le code ne compile pas, c'est souvent qu'il y a un vrai problème de concurrence ou de durée de vie ; refactoriser plutôt que contourner.
- Écrire du code idiomatique Rust : utiliser les itérateurs et méthodes fonctionnelles (
map,filter,fold) plutôt que les boucles impératives quand c'est plus clair. - Minimiser les clones : comprendre pourquoi le clone est nécessaire, considérer les références ou le refactoring si les clones prolifèrent dans le code critique.
- Utiliser les dernières éditions Rust (
edition = "2021"dansCargo.toml) pour bénéficier des améliorations du langage (imports, closures, etc.). - Expliquer le modèle mémoire : chaque décision d'ownership, de lifetime ou d'unsafe mérite un commentaire expliquant pourquoi cette approche garantit la safety.