Files
khadhroony-bot3/RUST_RULES.md
2026-07-23 16:37:12 +02:00

7.9 KiB
Raw Blame History

Règles Rust générales

Ce fichier contient les règles normatives applicables à tous les projets Rust. Elles sont indépendantes de khadhroony-bot2 et doivent pouvoir être réutilisées telles quelles dans un autre workspace.

En-têtes et versions de fichiers

  • Tout fichier texte qui supporte des commentaires commence par une ligne indiquant son chemin relatif dans le projet, puis une ligne version entière.
  • La version d'un fichier est incrémentée à chaque modification après validation de sa version précédente.
  • Les fichiers Rust utilisent // file: ... et // version: N.
  • Les fichiers Markdown utilisent <!-- file: ... --> et <!-- version: N -->.
  • Tous les fichiers texte se terminent par exactement une fin de ligne.

Langue et documentation

  • Les commentaires et rustdocs du code sont rédigés en anglais.
  • Les documents Markdown du projet sont rédigés dans la langue documentaire choisie par le projet.
  • Tout élément pub ou pub(crate) possède une rustdoc utile au point de déclaration.
  • Toute réexportation pub use ou pub(crate) use dans lib.rs ou main.rs possède également sa propre rustdoc copiée ou reformulée de manière équivalente. La documentation du point d'entrée doit permettre de comprendre l'API sans ouvrir le module interne.

Édition et lints obligatoires

  • L'édition Rust cible est Rust 2024, sauf contrainte explicitement documentée.
  • Chaque lib.rs et main.rs contient :
    • #![warn(missing_docs)] ;
    • #![deny(unreachable_pub)] ;
    • #![forbid(unsafe_code)].
  • Les lints Clippy obligatoires sont déclarés au niveau workspace et hérités par toutes les crates.
  • Les règles minimales sont : interdiction de unwrap, expect, ?, retours implicites, code unsafe, APIs publiques inaccessibles et imports globaux non justifiés.
  • Les tests peuvent disposer d'exceptions limitées pour unwrap et expect uniquement lorsqu'elles sont explicitement autorisées par la configuration Clippy.

La configuration workspace doit au minimum déclarer :

[workspace.lints.rust]
missing_docs = "warn"
unreachable_pub = "deny"
unsafe_code = "forbid"

[workspace.lints.clippy]
unwrap_used = "deny"
expect_used = "deny"
implicit_return = "deny"
needless_return = "allow"
useless_vec = "deny"
question_mark = "deny"
question_mark_used = "deny"
needless_match = "allow"
manual_ok_err = "allow"
manual_unwrap_or = "allow"
manual_map = "allow"
match_like_matches_macro = "allow"
single_match = "allow"
manual_unwrap_or_default = "allow"
manual_find = "allow"
explicit_counter_loop = "allow"
get_first = "allow"
implicit_saturating_sub = "allow"

Formatage

  • cargo fmt --all est exécuté après application de chaque delta ou correctif et avant les tests.
  • Les fichiers Rust ne contiennent pas de lignes vides à l'intérieur d'une fonction, d'une structure, d'une énumération ou d'une implémentation courte.
  • Les lignes vides séparent uniquement les fonctions, blocs impl, types et sections logiques.
  • Les exports de lib.rs ou main.rs ne contiennent aucune ligne vide à l'intérieur d'une série homogène de pub use ou pub(crate) use.
  • Les séries pub use et pub(crate) use forment deux groupes séparés lorsqu'elles coexistent.

Imports et chemins

  • use est interdit pour les constantes, fonctions, structures, énumérations, unions, alias de types, modules et macros.
  • use est autorisé uniquement pour un trait lorsque la résolution de méthode, une macro de dérivation ou une contrainte de langage l'exige réellement.
  • Un import de trait doit rester étroit et ne doit jamais importer simultanément des éléments non-traits par accolades.
  • Les imports globaux, glob imports et imports groupés par accolades sont interdits.
  • Pour un élément fourni par une crate externe au workspace, utiliser directement le chemin public le plus court exposé par cette crate. Exemple : utiliser external_crate::Struct, jamais external_crate::module::Struct si external_crate::Struct existe, et jamais use external_crate::Struct.
  • Pour un élément pub déclaré dans le workspace :
    • il est réexporté depuis le lib.rs ou main.rs de sa crate propriétaire ;
    • depuis une autre crate, il est appelé via owner_crate::Item ;
    • depuis sa propre crate, il est appelé via crate::Item, même depuis son module de déclaration.
  • Pour un élément pub(crate) :
    • il est réexporté depuis le lib.rs ou main.rs via pub(crate) use ;
    • il est appelé via crate::Item, même depuis son module de déclaration.
  • Un élément strictement privé à un module n'est pas réexporté et est appelé par son nom local uniquement. Il est interdit d'utiliser un chemin long comme crate::module::helper ou owner_crate::module::helper pour un helper privé du module courant.
  • Dans un sous-module de tests, un élément privé du module parent est appelé via super::Item. Un élément pub ou pub(crate) continue dêtre appelé via le point dentrée de crate le plus court, par exemple crate::Item.
  • Les exports ne sont jamais groupés avec des accolades. Un type, une fonction, une constante ou un alias correspond à une ligne de réexport distincte.

Visibilité et API de crate

  • Aucun pub mod n'est autorisé. Les modules restent privés et l'API est constituée par des réexports explicites.
  • Un élément pub inaccessible depuis le point d'entrée de sa crate est une erreur de conception, pas un simple avertissement.
  • Un élément pub(crate) utilisé hors de son module est réexporté au niveau du point d'entrée de la crate.
  • Les chemins internes de modules ne font pas partie de l'API stable.
  • Les méthodes inhérentes publiques restent appelées via le type réexporté ; les fonctions libres publiques sont appelées via le point d'entrée de crate.

Helpers et réutilisation

  • Un helper répété dans plusieurs modules d'une même crate est déplacé dans un module commun explicite, généralement helper.rs ou un module spécialisé plus précis.
  • Le nom helpers.rs ou helper.rs n'est utilisé que si aucune responsabilité métier plus précise ne convient.
  • Un helper général réutilisable par plusieurs crates est déplacé dans une crate commune appropriée et exposé publiquement.
  • Les types d'erreur généraux, identifiants de programme, primitives de validation et fonctions de sérialisation communes ne doivent pas être dupliqués entre crates.
  • La mutualisation ne doit pas créer de dépendance cyclique ni déplacer un comportement métier spécifique dans une crate générique.

Gestion des erreurs et contrôle de flux

  • unwrap, expect et panic sont interdits dans le code de production.
  • L'opérateur ? est interdit dans les chemins de production ; utiliser des match explicites avec erreurs contextualisées.
  • anyhow et thiserror ne sont pas utilisés par défaut.
  • Les erreurs publiques sont typées lorsque leur contrat est stable ; les diagnostics dynamiques restent bornés.
  • Les retours sont explicites conformément au lint clippy::implicit_return.

Sécurité et dépendances

  • Le code unsafe est interdit.
  • Une dépendance n'est ajoutée que si elle est réellement utilisée dans le chemin de compilation concerné.
  • Une dépendance utilisée uniquement dans les tests reste dans [dev-dependencies].
  • Les features sont minimales et explicites.

Contrôle avant livraison

Chaque livraison Rust exécute au minimum, dans cet ordre :

cargo fmt --all
python3 scripts/audit_rust_general_rules.py
python3 scripts/audit_khadhroony_workspace_rules.py
cargo test --workspace
cargo clippy --workspace --all-targets

Un projet peut utiliser une sélection de tests plus étroite pendant le développement, mais la fermeture d'une version exige le contrôle global.

Le wrapper python3 scripts/audit_rust_workspace_rules.py exécute les deux audits sans fusionner leurs responsabilités.