ADR-057 — libm Air (air-libm) : vendoring de libm (rust-lang) en surface math couche 1
Statut : Accepté (2026-07-01, par délégation d’autonomie BDFL pour ce lot ; gravé pour revue
a posteriori). RFC de structure (ADR-015). Companion d’ADR-053
(la libc Air s’appuie sur icu4x — dont la math flottante no_std) et d’ADR-024
(règle des 80 % / exceptions nommées). S’appuie sur l’audit docs/notes/audit-icu4x-rust-pur-fr.md
(§3 « le SEUL primitif système manquant — math flottante no_std (libm) » ; §8 « ce qu’Air N’A PAS :
un libm no_std »).
Catégorie : Architecture (couche 1, fondateur). Toute évolution structurante = RFC.
Contexte
L’audit icu4x (docs/notes/audit-icu4x-rust-pur-fr.md) a établi un fait net : le runtime d’icu4x est
déjà no_std et de calcul pur (Air a core + alloc), et le seul primitif système qui lui
manque est une bibliothèque mathématique flottante no_std — un libm. Deux consommateurs
incontournables du périmètre i18n d’Air en dépendent (§3) :
calendrical_calculations(dépendance d’icu_calendar) — math calendaire (astronomie des calendriers lunaires/solaires). Non contournable : le calendrier en a besoin.icu_segmenter/src/complex/lstm— math du modèle LSTM (segmentation par IA des écritures sans espaces : thaï/khmer/lao/birman), activée par la featureauto/lstmque le projet retient.
Tous deux passent par core_maths, une fine façade no_std sur la crate libm. Air ne fournit
aujourd’hui aucun libm no_std (la math flottante était explicitement hors de la v1 libc,
ADR-046). C’est, selon l’audit, le vrai manque systémique pour la libc /
i18n future. Une décision était requise (audit §8) : (a) fournir un libm Air, (b) restreindre
le périmètre. (b) ne suffit pas seule — même sans LSTM, le calendrier garde besoin de libm. Air
aura donc besoin d’un libm no_std.
Il n’y a aucun consommateur aujourd’hui : cet ADR pose une fondation (une bibliothèque en
attente de consommateurs), comme on coule des fondations avant d’élever les murs. Le câblage effectif
(icu4x → core_maths/libm sur *-linux-air) viendra avec la réimplémentation i18n (ADR-053).
Décision
D1 — Vendorer la crate libm (rust-lang) comme exception nommée (ADR-024, modèle icu4x)
Air vendore libm (la crate rust-lang) sous le régime des exceptions explicitement nommées
à la règle des 80 % du Principe 6 (ADR-024 ;
docs/EXCEPTIONS.md), exactement comme icu4x (ADR-016) et la crypto auditée (ADR-034). Justification
de l’exception :
- Rust pur,
no_std, zéro dépendance runtime.libmest un portage defdlibmen Rust pur,#![no_std], sans aucune dépendance transitive — il respecte la cible*-linux-airet la politique « zéro surface C/C++ » (#81 ; aucun*-sys, aucuncc). - Maintenu par le projet Rust, qualité
std.libmest fusionné danscompiler-builtins: c’est lelibmque lastdRust utilise elle-même sur les ciblesno_std/wasm. Sa correction (ULP, cas limites NaN/inf/dénormaux) est éprouvée et continûment testée par l’amont. - Réimplémentation disproportionnée et risquée. Réécrire un
libmcorrect from scratch (dizaines de fonctions transcendantes, précision ULP, sous-flots) serait énorme et porteur d’un risque de bugs numériques précisément là où Air ne peut pas se permettre l’à-peu-près. Le bénéfice « moins de code externe » serait annulé par le coût « plus de code maison moins testé » — le même raisonnement que pouricu4xet la crypto. - Licence permissive.
libm0.2.x est publié sousMIT(liste blanchedeny.toml; l’amontrust-lang/compiler-builtinsest dual MIT/Apache-2.0).
D2 — Surface exposée par une crate couche 1 air-libm (no_std, ré-export)
La math d’Air est exposée par une nouvelle crate crates/air-libm, #![no_std] (couche 1,
publish = false), qui ré-exporte la surface de libm (pub use libm::*;). Cette frontière
nommée donne à Air un point de contrôle unique sur sa surface math (un seul endroit où la version
est pinnée, auditée, documentée), sans réinventer ni masquer l’amont. air-libm n’a pas de logique
propre en v1 : c’est délibéré (une façade de ré-export), pour ne pas dupliquer ni dériver de l’amont.
D3 — Pas de consommateur en v1 (fondation)
Aucune crate Air ne consomme air-libm aujourd’hui. La crate est posée en prévision de la libc /
i18n (ADR-053) : c’est une fondation, pas un service actif. La preuve de viabilité est apportée par le
build *-linux-air (la cible réelle) et par les tests de fumée (D4), pas par un consommateur.
D4 — Mandat de test (Principe 1, couche 1 = 100 %)
air-libm n’ayant quasiment pas de code propre (ré-export), le 100 % de couverture de la couche 1
est atteint de façon non équivoque : il n’existe aucune ligne de logique air-libm susceptible
d’être manquée (un pub use ne génère pas de région exécutable). Des tests de fumée à valeurs
connues exercent néanmoins la surface ré-exportée (sqrt, cbrt, cos, exp, pow, floor,
fabs, log, hypot, sin, tan, …, avec tolérance epsilon sur les transcendantes — jamais d’==
nu) pour prouver que la passerelle fonctionne. libm lui-même (la dépendance externe) n’est pas
mesuré (externe, comme icu4x / la crypto auditée).
Conséquences
- Air dispose d’une surface math
no_stdnommée et pinnée — la dernière brique système qui manquait à la réimplémentation i18n (ADR-053) est en place, prête à être câblée. - Une exception de dépendance de plus, explicitement consignée (
docs/EXCEPTIONS.md+crates/air-libm/DEPENDENCIES.md), auditée parcargo deny(licence) etcargo audit. - Zéro coût runtime tant qu’aucun consommateur ne tire
air-libm: la crate est compilée et testée, mais aucune binaire produit ne l’embarque encore.
Alternatives rejetées
- Réécrire
libmfrom scratch. Énorme, risque ULP/cas-limites élevé, pour une qualité de tests et de revue inférieure à l’amontrust-lang. Disproportionné (D1). - Dépendance
libmnon nommée (déclarée comme une dépendance ordinaire sans entrée d’exception). Viole le Principe 6 / ADR-024 : sous le seuil des 80 %, toute dépendance structurante exige une exception explicite. Rejeté au profit du vendoring nommé (modèleicu4x). - Restreindre le périmètre i18n pour éviter
libm. Insuffisant : le calendrier (non contournable) garde besoin de math flottante (audit §3/§8). Rejeté. - Câbler un consommateur dès maintenant. Prématuré : la réimplémentation i18n (ADR-053) n’est pas
faite. On pose la fondation et on prouve le build
*-linux-air, sans inventer d’usage.
Mise en œuvre (esquisse)
crates/air-libm(no_std, deplibm = "=0.2.x") :pub use libm::*;+ doc de module (rôle, attribution amont) + tests de fumée 100 %.- Workspace : ajout aux
members+libmdans[workspace.dependencies](pin strict, repro ADR-025). - Doc : ADR-057,
EXCEPTIONS.md(entréelibm),DEPENDENCIES.md, registre ADR, SUMMARY, INDEX. - Preuve de build
*-linux-air(crate-sonde jetablert/, non committée).