Contexte et objectifs
Le nouveau vérificateur d'emprunts de Valen s’appuie sur la proposition "Group Borrowing" conçue par Nick Smith. L’auteur indique que l’objectif est d’allier la puissance du système de Rust à la souplesse du comptage de références ou du ramasse‑miettes, tout en conservant une garantie d’absence d’use‑after‑free à la compilation. Cette ambition se traduit par trois défis identifiés : rendre le vérificateur plus relâché, le faire analyser des structures de données plus complexes, et permettre la coexistence avec d’autres modèles de gestion mémoire.
Valen combine ainsi le group borrowing avec l’approche de Vale et assure une interopérabilité directe avec le code Rust, ce qui le différencie des implémentations précédentes qui restaient cantonnées à un seul paradigme.
Mécanisme du group borrowing
Le principe central consiste à ce que le compilateur se souvienne du chemin d’accès exact d’une référence. Chaque référence possède ainsi une « ownership path » qui décrit la localisation de l’objet dans la structure de données. Lors de l’invalidation d’une partie du programme, le vérificateur compare les chemins pour détecter les accès après libération, sans imposer la règle classique « shared‑xor‑mutable ». Cette relaxation se limite à interdire les usages après libération, ce qui élargit considérablement les patterns acceptés.
Le système introduit plusieurs notions : single ownership paths, mutable‑in‑immutable temporary uniqueness, wildcard descendant paths et temporary uniqueness. Ces concepts permettent de communiquer, via les signatures de fonctions, quelles parties de la mémoire seront invalidées, tout en conservant la possibilité d’écrire à travers plusieurs références simultanées.
Exemples d’applications et limites
valen struct Entity { hp int; }
struct World { entities Vec<Entity>; }
func main() int {
let world = World(Vec<Entity>.new());
world.entities.push(Entity(42));
let first_ref = &world.entities[0];
world.entities = Vec<Entity>.new();
// Compile error: Used a borrow after invalidated
return first_ref.hp;
}Dans cet extrait, le compilateur signale une utilisation après invalidation, démontrant la capacité du vérificateur à détecter les use‑after‑free à la compilation.
valen func main() int {
let list = Vec<int>.new();
let ref_a = &list;
let ref_b = &list;
ref_a.push(42);
ref_b.push(73);
return 42;
}Ce second exemple montre que deux références mutables peuvent écrire simultanément sur la même collection, ce qui serait interdit par le modèle Rust traditionnel. Valen accepte donc des patterns courants en C++ (par ex. le pattern ScopeGuard) tout en restant sûr au niveau compile‑time. Cependant, l’article ne fournit pas de métriques de performance ou de limites précises ; l’absence de données chiffrées empêche d’évaluer l’impact sur le temps de compilation ou la taille du binaire.
Adoption et perspectives
Depuis la publication de la proposition initiale, plusieurs langages ont intégré le group borrowing : le langage Carbon de Google, Ante, Plecra, Zeta et Fang. Valen se distingue en combinant ce mécanisme avec l’interopérabilité Rust, ouvrant la voie à des projets hybrides où le code Rust peut coexister avec des modèles de comptage de références ou de références générationnelles. Le texte indique que la plupart des équipes cherchent à résoudre le conflit « shared‑xor‑mutable » en adoptant la règle « no use‑after‑free », mais aucune étude comparative n’est présentée. En l’état, Valen constitue une preuve de concept avancée, mais la communauté devra encore valider sa robustesse à grande échelle.