@@ -318,22 +318,25 @@ impl Error for VarError {
318
318
///
319
319
/// # Safety
320
320
///
321
- /// Even though this function is currently not marked as `unsafe`, it needs to
322
- /// be because invoking it can cause undefined behaviour. The function will be
323
- /// marked `unsafe` in a future version of Rust. This is tracked in
324
- /// [rust#27970](https://github.com/rust-lang/rust/issues/27970).
325
- ///
326
321
/// This function is safe to call in a single-threaded program.
327
322
///
328
- /// In multi-threaded programs, you must ensure that are no other threads
329
- /// concurrently writing or *reading*(!) from the environment through functions
330
- /// other than the ones in this module. You are responsible for figuring out
331
- /// how to achieve this, but we strongly suggest not using `set_var` or
332
- /// `remove_var` in multi-threaded programs at all.
333
- ///
334
- /// Most C libraries, including libc itself do not advertise which functions
335
- /// read from the environment. Even functions from the Rust standard library do
336
- /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`].
323
+ /// This function is also always safe to call on Windows, in single-threaded
324
+ /// and multi-threaded programs.
325
+ ///
326
+ /// In multi-threaded programs on other operating systems, we strongly suggest
327
+ /// not using `set_var` or `remove_var` at all. The exact requirement is: you
328
+ /// must ensure that there are no other threads concurrently writing or
329
+ /// *reading*(!) the environment through functions or global variables other
330
+ /// than the ones in this module. The problem is that these operating systems
331
+ /// do not provide a thread-safe way to read the environment, and most C
332
+ /// libraries, including libc itself, do not advertise which functions read
333
+ /// from the environment. Even functions from the Rust standard library may
334
+ /// read the environment without going through this module, e.g. for DNS
335
+ /// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about
336
+ /// which functions may read from the environment in future versions of a
337
+ /// library. All this makes it not practically possible for you to guarantee
338
+ /// that no other thread will read the environment, so the only safe option is
339
+ /// to not use `set_var` or `remove_var` in multi-threaded programs at all.
337
340
///
338
341
/// Discussion of this unsafety on Unix may be found in:
339
342
///
@@ -353,15 +356,26 @@ impl Error for VarError {
353
356
/// use std::env;
354
357
///
355
358
/// let key = "KEY";
356
- /// env::set_var(key, "VALUE");
359
+ /// unsafe {
360
+ /// env::set_var(key, "VALUE");
361
+ /// }
357
362
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
358
363
/// ```
364
+ #[ cfg( not( bootstrap) ) ]
365
+ #[ rustc_deprecated_safe_2024]
359
366
#[ stable( feature = "env" , since = "1.0.0" ) ]
360
- pub fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
367
+ pub unsafe fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
361
368
_set_var ( key. as_ref ( ) , value. as_ref ( ) )
362
369
}
363
370
364
- fn _set_var ( key : & OsStr , value : & OsStr ) {
371
+ #[ cfg( bootstrap) ]
372
+ #[ allow( missing_docs) ]
373
+ #[ stable( feature = "env" , since = "1.0.0" ) ]
374
+ pub fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
375
+ unsafe { _set_var ( key. as_ref ( ) , value. as_ref ( ) ) }
376
+ }
377
+
378
+ unsafe fn _set_var ( key : & OsStr , value : & OsStr ) {
365
379
os_imp:: setenv ( key, value) . unwrap_or_else ( |e| {
366
380
panic ! ( "failed to set environment variable `{key:?}` to `{value:?}`: {e}" )
367
381
} )
@@ -371,22 +385,25 @@ fn _set_var(key: &OsStr, value: &OsStr) {
371
385
///
372
386
/// # Safety
373
387
///
374
- /// Even though this function is currently not marked as `unsafe`, it needs to
375
- /// be because invoking it can cause undefined behaviour. The function will be
376
- /// marked `unsafe` in a future version of Rust. This is tracked in
377
- /// [rust#27970](https://github.com/rust-lang/rust/issues/27970).
378
- ///
379
388
/// This function is safe to call in a single-threaded program.
380
389
///
381
- /// In multi-threaded programs, you must ensure that are no other threads
382
- /// concurrently writing or *reading*(!) from the environment through functions
383
- /// other than the ones in this module. You are responsible for figuring out
384
- /// how to achieve this, but we strongly suggest not using `set_var` or
385
- /// `remove_var` in multi-threaded programs at all.
386
- ///
387
- /// Most C libraries, including libc itself do not advertise which functions
388
- /// read from the environment. Even functions from the Rust standard library do
389
- /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`].
390
+ /// This function is also always safe to call on Windows, in single-threaded
391
+ /// and multi-threaded programs.
392
+ ///
393
+ /// In multi-threaded programs on other operating systems, we strongly suggest
394
+ /// not using `set_var` or `remove_var` at all. The exact requirement is: you
395
+ /// must ensure that there are no other threads concurrently writing or
396
+ /// *reading*(!) the environment through functions or global variables other
397
+ /// than the ones in this module. The problem is that these operating systems
398
+ /// do not provide a thread-safe way to read the environment, and most C
399
+ /// libraries, including libc itself, do not advertise which functions read
400
+ /// from the environment. Even functions from the Rust standard library may
401
+ /// read the environment without going through this module, e.g. for DNS
402
+ /// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about
403
+ /// which functions may read from the environment in future versions of a
404
+ /// library. All this makes it not practically possible for you to guarantee
405
+ /// that no other thread will read the environment, so the only safe option is
406
+ /// to not use `set_var` or `remove_var` in multi-threaded programs at all.
390
407
///
391
408
/// Discussion of this unsafety on Unix may be found in:
392
409
///
@@ -403,22 +420,35 @@ fn _set_var(key: &OsStr, value: &OsStr) {
403
420
///
404
421
/// # Examples
405
422
///
406
- /// ```
423
+ /// ```no_run
407
424
/// use std::env;
408
425
///
409
426
/// let key = "KEY";
410
- /// env::set_var(key, "VALUE");
427
+ /// unsafe {
428
+ /// env::set_var(key, "VALUE");
429
+ /// }
411
430
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
412
431
///
413
- /// env::remove_var(key);
432
+ /// unsafe {
433
+ /// env::remove_var(key);
434
+ /// }
414
435
/// assert!(env::var(key).is_err());
415
436
/// ```
437
+ #[ cfg( not( bootstrap) ) ]
438
+ #[ rustc_deprecated_safe_2024]
416
439
#[ stable( feature = "env" , since = "1.0.0" ) ]
417
- pub fn remove_var < K : AsRef < OsStr > > ( key : K ) {
440
+ pub unsafe fn remove_var < K : AsRef < OsStr > > ( key : K ) {
418
441
_remove_var ( key. as_ref ( ) )
419
442
}
420
443
421
- fn _remove_var ( key : & OsStr ) {
444
+ #[ cfg( bootstrap) ]
445
+ #[ allow( missing_docs) ]
446
+ #[ stable( feature = "env" , since = "1.0.0" ) ]
447
+ pub fn remove_var < K : AsRef < OsStr > > ( key : K ) {
448
+ unsafe { _remove_var ( key. as_ref ( ) ) }
449
+ }
450
+
451
+ unsafe fn _remove_var ( key : & OsStr ) {
422
452
os_imp:: unsetenv ( key)
423
453
. unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{key:?}`: {e}" ) )
424
454
}
0 commit comments