about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-29 05:55:46 +0000
committerbors <bors@rust-lang.org>2023-08-29 05:55:46 +0000
commitd9c11c65ee93b6dfd0c71f17812c68d316fce183 (patch)
tree1451f2e711b883122df8c5f3f7baa19ef46a1c89 /library
parent63bf24090e38463bc2125170a0c3e98e0d20a85c (diff)
parentfb3565a848af21af18c26156f0acae9115257e46 (diff)
Auto merge of #3042 - rust-lang:rustup-2023-08-29, r=RalfJung
Automatic sync from rustc
Diffstat (limited to 'library')
-rw-r--r--library/alloc/src/alloc.rs32
-rw-r--r--library/alloc/src/macros.rs7
-rw-r--r--library/core/src/macros/mod.rs3
-rw-r--r--library/core/src/macros/panic.md30
-rw-r--r--library/core/src/marker.rs10
-rw-r--r--library/core/src/net/ip_addr.rs8
-rw-r--r--library/core/src/num/f32.rs20
-rw-r--r--library/core/src/num/f64.rs20
-rw-r--r--library/core/src/ops/drop.rs10
-rw-r--r--library/core/src/panic/panic_info.rs15
-rw-r--r--library/core/src/panicking.rs37
-rw-r--r--library/core/src/time.rs8
-rw-r--r--library/core/tests/time.rs1
-rw-r--r--library/std/src/alloc.rs26
-rw-r--r--library/std/src/macros.rs12
-rw-r--r--library/std/src/os/unix/net/tests.rs2
-rw-r--r--library/std/src/os/windows/process.rs69
-rw-r--r--library/std/src/panicking.rs36
-rw-r--r--library/std/src/process/tests.rs85
-rw-r--r--library/std/src/sys/hermit/mod.rs1
-rw-r--r--library/std/src/sys/hermit/net.rs8
-rw-r--r--library/std/src/sys/unix/alloc.rs6
-rw-r--r--library/std/src/sys/windows/c/windows_sys.lst5
-rw-r--r--library/std/src/sys/windows/c/windows_sys.rs37
-rw-r--r--library/std/src/sys/windows/process.rs112
-rw-r--r--library/std/src/time.rs24
26 files changed, 554 insertions, 70 deletions
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 5205ed9fb50..a548de814c5 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -343,18 +343,31 @@ extern "Rust" {
     fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
 }
 
-/// Abort on memory allocation error or failure.
+/// Signal a memory allocation error.
 ///
-/// Callers of memory allocation APIs wishing to abort computation
+/// Callers of memory allocation APIs wishing to cease execution
 /// in response to an allocation error are encouraged to call this function,
-/// rather than directly invoking `panic!` or similar.
+/// rather than directly invoking [`panic!`] or similar.
 ///
-/// The default behavior of this function is to print a message to standard error
-/// and abort the process.
-/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
+/// This function is guaranteed to diverge (not return normally with a value), but depending on
+/// global configuration, it may either panic (resulting in unwinding or aborting as per
+/// configuration for all panics), or abort the process (with no unwinding).
+///
+/// The default behavior is:
+///
+///  * If the binary links against `std` (typically the case), then
+///   print a message to standard error and abort the process.
+///   This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
+///   Future versions of Rust may panic by default instead.
+///
+/// * If the binary does not link against `std` (all of its crates are marked
+///   [`#![no_std]`][no_std]), then call [`panic!`] with a message.
+///   [The panic handler] applies as to any panic.
 ///
 /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
 /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
+/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute
+/// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
 #[cfg(all(not(no_global_oom_handling), not(test)))]
@@ -395,9 +408,10 @@ pub mod __alloc_error_handler {
         if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
             panic!("memory allocation of {size} bytes failed")
         } else {
-            core::panicking::panic_nounwind_fmt(format_args!(
-                "memory allocation of {size} bytes failed"
-            ))
+            core::panicking::panic_nounwind_fmt(
+                format_args!("memory allocation of {size} bytes failed"),
+                /* force_no_backtrace */ false,
+            )
         }
     }
 }
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index 4c6ae8f2579..3f19561e1ac 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -79,10 +79,12 @@ macro_rules! vec {
 ///
 /// The first argument `format!` receives is a format string. This must be a string
 /// literal. The power of the formatting string is in the `{}`s contained.
-///
 /// Additional parameters passed to `format!` replace the `{}`s within the
 /// formatting string in the order given unless named or positional parameters
-/// are used; see [`std::fmt`] for more information.
+/// are used.
+///
+/// See [the formatting syntax documentation in `std::fmt`](../std/fmt/index.html)
+/// for details.
 ///
 /// A common use for `format!` is concatenation and interpolation of strings.
 /// The same convention is used with [`print!`] and [`write!`] macros,
@@ -91,7 +93,6 @@ macro_rules! vec {
 /// To convert a single value to a string, use the [`to_string`] method. This
 /// will use the [`Display`] formatting trait.
 ///
-/// [`std::fmt`]: ../std/fmt/index.html
 /// [`print!`]: ../std/macro.print.html
 /// [`write!`]: core::write
 /// [`to_string`]: crate::string::ToString
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 14cc523b0c1..46628bcea00 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -849,7 +849,8 @@ pub(crate) mod builtin {
     /// assert_eq!(display, debug);
     /// ```
     ///
-    /// For more information, see the documentation in [`std::fmt`].
+    /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+    /// for details of the macro argument syntax, and further information.
     ///
     /// [`Display`]: crate::fmt::Display
     /// [`Debug`]: crate::fmt::Debug
diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md
index 8b549e187ba..60100c2655a 100644
--- a/library/core/src/macros/panic.md
+++ b/library/core/src/macros/panic.md
@@ -8,8 +8,8 @@ tests. `panic!` is closely tied with the `unwrap` method of both
 [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call
 `panic!` when they are set to [`None`] or [`Err`] variants.
 
-When using `panic!()` you can specify a string payload, that is built using
-the [`format!`] syntax. That payload is used when injecting the panic into
+When using `panic!()` you can specify a string payload that is built using
+[formatting syntax]. That payload is used when injecting the panic into
 the calling Rust thread, causing the thread to panic entirely.
 
 The behavior of the default `std` hook, i.e. the code that runs directly
@@ -18,6 +18,7 @@ after the panic is invoked, is to print the message payload to
 call. You can override the panic hook using [`std::panic::set_hook()`].
 Inside the hook a panic can be accessed as a `&dyn Any + Send`,
 which contains either a `&str` or `String` for regular `panic!()` invocations.
+(Whether a particular invocation contains the payload at type `&str` or `String` is unspecified and can change.)
 To panic with a value of another other type, [`panic_any`] can be used.
 
 See also the macro [`compile_error!`], for raising errors during compilation.
@@ -55,7 +56,7 @@ For more detailed information about error handling check out the [book] or the
 [`panic_any`]: ../std/panic/fn.panic_any.html
 [`Box`]: ../std/boxed/struct.Box.html
 [`Any`]: crate::any::Any
-[`format!`]: ../std/macro.format.html
+[`format!` syntax]: ../std/fmt/index.html
 [book]: ../book/ch09-00-error-handling.html
 [`std::result`]: ../std/result/index.html
 
@@ -64,6 +65,29 @@ For more detailed information about error handling check out the [book] or the
 If the main thread panics it will terminate all your threads and end your
 program with code `101`.
 
+# Editions
+
+Behavior of the panic macros changed over editions.
+
+## 2021 and later
+
+In Rust 2021 and later, `panic!` always requires a format string and
+the applicable format arguments, and is the same in `core` and `std`.
+Use [`std::panic::panic_any(x)`](../std/panic/fn.panic_any.html) to
+panic with an arbitrary payload.
+
+## 2018 and 2015
+
+In Rust Editions prior to 2021, `std::panic!(x)` with a single
+argument directly uses that argument as a payload.
+This is true even if the argument is a string literal.
+For example, `panic!("problem: {reason}")` panics with a
+payload of literally `"problem: {reason}"` (a `&'static str`).
+
+`core::panic!(x)` with a single argument requires that `x` be `&str`,
+but otherwise behaves like `std::panic!`. In particular, the string
+need not be a literal, and is not interpreted as a format string.
+
 # Examples
 
 ```should_panic
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index aec287226a0..5ec751e5168 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -76,11 +76,8 @@ macro marker_impls {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "Send")]
 #[rustc_on_unimplemented(
-    on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
     message = "`{Self}` cannot be sent between threads safely",
-    label = "`{Self}` cannot be sent between threads safely",
-    note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
-            <https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
+    label = "`{Self}` cannot be sent between threads safely"
 )]
 pub unsafe auto trait Send {
     // empty.
@@ -631,11 +628,8 @@ impl<T: ?Sized> Copy for &T {}
         any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
         note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
     ),
-    on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"),
     message = "`{Self}` cannot be shared between threads safely",
-    label = "`{Self}` cannot be shared between threads safely",
-    note = "consider using `std::sync::Arc<{Self}>`; for more information visit \
-            <https://doc.rust-lang.org/book/ch16-03-shared-state.html>"
+    label = "`{Self}` cannot be shared between threads safely"
 )]
 pub unsafe auto trait Sync {
     // FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 56460c75eba..6a36dfec098 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1856,13 +1856,7 @@ impl fmt::Display for Ipv6Addr {
         if f.precision().is_none() && f.width().is_none() {
             let segments = self.segments();
 
-            // Special case for :: and ::1; otherwise they get written with the
-            // IPv4 formatter
-            if self.is_unspecified() {
-                f.write_str("::")
-            } else if self.is_loopback() {
-                f.write_str("::1")
-            } else if let Some(ipv4) = self.to_ipv4_mapped() {
+            if let Some(ipv4) = self.to_ipv4_mapped() {
                 write!(f, "::ffff:{}", ipv4)
             } else {
                 #[derive(Copy, Clone, Default)]
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index d050d21c8c5..3144db19707 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -277,6 +277,14 @@ pub mod consts {
     #[stable(feature = "tau_constant", since = "1.47.0")]
     pub const TAU: f32 = 6.28318530717958647692528676655900577_f32;
 
+    /// The golden ratio (φ)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const PHI: f32 = 1.618033988749894848204586834365638118_f32;
+
+    /// The Euler-Mascheroni constant (γ)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const EGAMMA: f32 = 0.577215664901532860606512090082402431_f32;
+
     /// π/2
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
@@ -301,6 +309,10 @@ pub mod consts {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
 
+    /// 1/sqrt(π)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
@@ -317,6 +329,14 @@ pub mod consts {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
 
+    /// sqrt(3)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const SQRT_3: f32 = 1.732050807568877293527446341505872367_f32;
+
+    /// 1/sqrt(3)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32;
+
     /// Euler's number (e)
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const E: f32 = 2.71828182845904523536028747135266250_f32;
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index d9a738191f7..20833defc41 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -277,6 +277,14 @@ pub mod consts {
     #[stable(feature = "tau_constant", since = "1.47.0")]
     pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
 
+    /// The golden ratio (φ)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const PHI: f64 = 1.618033988749894848204586834365638118_f64;
+
+    /// The Euler-Mascheroni constant (γ)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const EGAMMA: f64 = 0.577215664901532860606512090082402431_f64;
+
     /// π/2
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
@@ -301,6 +309,10 @@ pub mod consts {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64;
 
+    /// 1/sqrt(π)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
@@ -317,6 +329,14 @@ pub mod consts {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
 
+    /// sqrt(3)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const SQRT_3: f64 = 1.732050807568877293527446341505872367_f64;
+
+    /// 1/sqrt(3)
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64;
+
     /// Euler's number (e)
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const E: f64 = 2.71828182845904523536028747135266250_f64;
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index 9ebf426be95..21c23dabfc2 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -217,8 +217,13 @@ pub trait Drop {
     ///
     /// # Panics
     ///
-    /// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
-    /// in a `drop` implementation will likely abort.
+    /// Implementations should generally avoid [`panic!`]ing, because `drop()` may itself be called
+    /// during unwinding due to a panic, and if the `drop()` panics in that situation (a “double
+    /// panic”), this will likely abort the program. It is possible to check [`panicking()`] first,
+    /// which may be desirable for a `Drop` implementation that is reporting a bug of the kind
+    /// “you didn't finish using this before it was dropped”; but most types should simply clean up
+    /// their owned allocations or other resources and return normally from `drop()`, regardless of
+    /// what state they are in.
     ///
     /// Note that even if this panics, the value is considered to be dropped;
     /// you must not cause `drop` to be called again. This is normally automatically
@@ -227,6 +232,7 @@ pub trait Drop {
     ///
     /// [E0040]: ../../error_codes/E0040.html
     /// [`panic!`]: crate::panic!
+    /// [`panicking()`]: ../../std/thread/fn.panicking.html
     /// [`mem::drop`]: drop
     /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index c7f04f11ef6..c77e9675a6a 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -28,6 +28,7 @@ pub struct PanicInfo<'a> {
     message: Option<&'a fmt::Arguments<'a>>,
     location: &'a Location<'a>,
     can_unwind: bool,
+    force_no_backtrace: bool,
 }
 
 impl<'a> PanicInfo<'a> {
@@ -42,9 +43,10 @@ impl<'a> PanicInfo<'a> {
         message: Option<&'a fmt::Arguments<'a>>,
         location: &'a Location<'a>,
         can_unwind: bool,
+        force_no_backtrace: bool,
     ) -> Self {
         struct NoPayload;
-        PanicInfo { location, message, payload: &NoPayload, can_unwind }
+        PanicInfo { location, message, payload: &NoPayload, can_unwind, force_no_backtrace }
     }
 
     #[unstable(
@@ -141,6 +143,17 @@ impl<'a> PanicInfo<'a> {
     pub fn can_unwind(&self) -> bool {
         self.can_unwind
     }
+
+    #[unstable(
+        feature = "panic_internals",
+        reason = "internal details of the implementation of the `panic!` and related macros",
+        issue = "none"
+    )]
+    #[doc(hidden)]
+    #[inline]
+    pub fn force_no_backtrace(&self) -> bool {
+        self.force_no_backtrace
+    }
 }
 
 #[stable(feature = "panic_hook_display", since = "1.26.0")]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index ab6aa0df428..281f8c1e166 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -61,7 +61,12 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
         fn panic_impl(pi: &PanicInfo<'_>) -> !;
     }
 
-    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
+    let pi = PanicInfo::internal_constructor(
+        Some(&fmt),
+        Location::caller(),
+        /* can_unwind */ true,
+        /* force_no_backtrace */ false,
+    );
 
     // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
     unsafe { panic_impl(&pi) }
@@ -77,7 +82,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
 // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
 // which causes a "panic in a function that cannot unwind".
 #[rustc_nounwind]
-pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
+pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
     }
@@ -90,7 +95,12 @@ pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
     }
 
     // PanicInfo with the `can_unwind` flag set to false forces an abort.
-    let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
+    let pi = PanicInfo::internal_constructor(
+        Some(&fmt),
+        Location::caller(),
+        /* can_unwind */ false,
+        force_no_backtrace,
+    );
 
     // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
     unsafe { panic_impl(&pi) }
@@ -123,7 +133,15 @@ pub const fn panic(expr: &'static str) -> ! {
 #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
 #[rustc_nounwind]
 pub fn panic_nounwind(expr: &'static str) -> ! {
-    panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
+    panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false);
+}
+
+/// Like `panic_nounwind`, but also inhibits showing a backtrace.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[rustc_nounwind]
+pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
+    panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true);
 }
 
 #[inline]
@@ -172,9 +190,12 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
         super::intrinsics::abort()
     }
 
-    panic_nounwind_fmt(format_args!(
-        "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}"
-    ))
+    panic_nounwind_fmt(
+        format_args!(
+            "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}"
+        ),
+        /* force_no_backtrace */ false,
+    )
 }
 
 /// Panic because we cannot unwind out of a function.
@@ -205,7 +226,7 @@ fn panic_cannot_unwind() -> ! {
 #[rustc_nounwind]
 fn panic_in_cleanup() -> ! {
     // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`.
-    panic_nounwind("panic in a destructor during cleanup")
+    panic_nounwind_nobacktrace("panic in a destructor during cleanup")
 }
 
 /// This function is used instead of panic_fmt in const eval.
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index b08d5782ab6..1e8d28979e6 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -656,10 +656,10 @@ impl Duration {
     #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
     pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
         if rhs != 0 {
-            let secs = self.secs / (rhs as u64);
-            let carry = self.secs - secs * (rhs as u64);
-            let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
-            let nanos = self.nanos.0 / rhs + (extra_nanos as u32);
+            let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64));
+            let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs);
+            nanos +=
+                ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32;
             debug_assert!(nanos < NANOS_PER_SEC);
             Some(Duration::new(secs, nanos))
         } else {
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index 872611937cc..bd6e63edbb9 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -170,6 +170,7 @@ fn saturating_mul() {
 fn div() {
     assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
     assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
+    assert_eq!(Duration::new(1, 1) / 7, Duration::new(0, 142_857_143));
     assert_eq!(Duration::new(99, 999_999_000) / 100, Duration::new(0, 999_999_990));
 }
 
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 1eae7fa6a95..bb786bd59dc 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -290,15 +290,29 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 
 /// Registers a custom allocation error hook, replacing any that was previously registered.
 ///
-/// The allocation error hook is invoked when an infallible memory allocation fails, before
-/// the runtime aborts. The default hook prints a message to standard error,
-/// but this behavior can be customized with the [`set_alloc_error_hook`] and
-/// [`take_alloc_error_hook`] functions.
+/// The allocation error hook is invoked when an infallible memory allocation fails — that is,
+/// as a consequence of calling [`handle_alloc_error`] — before the runtime aborts.
 ///
-/// The hook is provided with a `Layout` struct which contains information
+/// The allocation error hook is a global resource. [`take_alloc_error_hook`] may be used to
+/// retrieve a previously registered hook and wrap or discard it.
+///
+/// # What the provided `hook` function should expect
+///
+/// The hook function is provided with a [`Layout`] struct which contains information
 /// about the allocation that failed.
 ///
-/// The allocation error hook is a global resource.
+/// The hook function may choose to panic or abort; in the event that it returns normally, this
+/// will cause an immediate abort.
+///
+/// Since [`take_alloc_error_hook`] is a safe function that allows retrieving the hook, the hook
+/// function must be _sound_ to call even if no memory allocations were attempted.
+///
+/// # The default hook
+///
+/// The default hook, used if [`set_alloc_error_hook`] is never called, prints a message to
+/// standard error (and then returns, causing the runtime to abort the process).
+/// Compiler options may cause it to panic instead, and the default behavior may be changed
+/// to panicking in future versions of Rust.
 ///
 /// # Examples
 ///
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index ba1b8cbfa56..34b8b6b97b5 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -41,6 +41,9 @@ macro_rules! panic {
 /// Use `print!` only for the primary output of your program. Use
 /// [`eprint!`] instead to print error and progress messages.
 ///
+/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+/// for details of the macro argument syntax.
+///
 /// [flush]: crate::io::Write::flush
 /// [`println!`]: crate::println
 /// [`eprint!`]: crate::eprint
@@ -103,6 +106,9 @@ macro_rules! print {
 /// Use `println!` only for the primary output of your program. Use
 /// [`eprintln!`] instead to print error and progress messages.
 ///
+/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+/// for details of the macro argument syntax.
+///
 /// [`std::fmt`]: crate::fmt
 /// [`eprintln!`]: crate::eprintln
 /// [lock]: crate::io::Stdout
@@ -150,6 +156,9 @@ macro_rules! println {
 /// [`io::stderr`]: crate::io::stderr
 /// [`io::stdout`]: crate::io::stdout
 ///
+/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+/// for details of the macro argument syntax.
+///
 /// # Panics
 ///
 /// Panics if writing to `io::stderr` fails.
@@ -181,6 +190,9 @@ macro_rules! eprint {
 /// Use `eprintln!` only for error and progress messages. Use `println!`
 /// instead for the primary output of your program.
 ///
+/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+/// for details of the macro argument syntax.
+///
 /// [`io::stderr`]: crate::io::stderr
 /// [`io::stdout`]: crate::io::stdout
 /// [`println!`]: crate::println
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 3d4302e665c..6a6af9efd78 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -662,7 +662,7 @@ fn test_send_vectored_fds_unix_stream() {
     }
 }
 
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
 #[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_send_vectored_with_ancillary_to_unix_datagram() {
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 073168cf2d2..5d87216ff1b 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -192,6 +192,66 @@ pub trait CommandExt: Sealed {
     /// ```
     #[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")]
     fn async_pipes(&mut self, always_async: bool) -> &mut process::Command;
+
+    /// Sets a raw attribute on the command, providing extended configuration options for Windows processes.
+    ///
+    /// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values.
+    /// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe.
+    ///
+    /// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute.
+    /// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings.
+    ///
+    /// # Note
+    ///
+    /// The maximum number of raw attributes is the value of [`u32::MAX`].
+    /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` indicating that the maximum number of attributes has been exceeded.
+    /// # Safety
+    ///
+    /// The usage of raw attributes is potentially unsafe and should be done with caution. Incorrect attribute values or improper configuration can lead to unexpected behavior or errors.
+    ///
+    /// # Example
+    ///
+    /// The following example demonstrates how to create a child process with a specific parent process ID using a raw attribute.
+    ///
+    /// ```rust
+    /// #![feature(windows_process_extensions_raw_attribute)]
+    /// use std::os::windows::{process::CommandExt, io::AsRawHandle};
+    /// use std::process::Command;
+    ///
+    /// # struct ProcessDropGuard(std::process::Child);
+    /// # impl Drop for ProcessDropGuard {
+    /// #     fn drop(&mut self) {
+    /// #         let _ = self.0.kill();
+    /// #     }
+    /// # }
+    ///
+    /// let parent = Command::new("cmd").spawn()?;
+    ///
+    /// let mut child_cmd = Command::new("cmd");
+    ///
+    /// const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
+    ///
+    /// unsafe {
+    ///     child_cmd.raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.as_raw_handle() as isize);
+    /// }
+    /// #
+    /// # let parent = ProcessDropGuard(parent);
+    ///
+    /// let mut child = child_cmd.spawn()?;
+    ///
+    /// # child.kill()?;
+    /// # Ok::<(), std::io::Error>(())
+    /// ```
+    ///
+    /// # Safety Note
+    ///
+    /// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used.
+    #[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")]
+    unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
+        &mut self,
+        attribute: usize,
+        value: T,
+    ) -> &mut process::Command;
 }
 
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
@@ -219,6 +279,15 @@ impl CommandExt for process::Command {
         let _ = always_async;
         self
     }
+
+    unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
+        &mut self,
+        attribute: usize,
+        value: T,
+    ) -> &mut process::Command {
+        self.as_inner_mut().raw_attribute(attribute, value);
+        self
+    }
 }
 
 #[unstable(feature = "windows_process_extensions_main_thread_handle", issue = "96723")]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 6ff7b19f293..b20e5464e6e 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -246,7 +246,9 @@ fn default_hook(info: &PanicInfo<'_>) {
 pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path::Path>) {
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
-    let backtrace = if panic_count::get_count() >= 2 {
+    let backtrace = if info.force_no_backtrace() {
+        None
+    } else if panic_count::get_count() >= 2 {
         BacktraceStyle::full()
     } else {
         crate::panic::get_backtrace_style()
@@ -294,7 +296,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
                     }
                 }
             }
-            // If backtraces aren't supported, do nothing.
+            // If backtraces aren't supported or are forced-off, do nothing.
             None => {}
         }
     };
@@ -615,14 +617,23 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
     let loc = info.location().unwrap(); // The current implementation always returns Some
     let msg = info.message().unwrap(); // The current implementation always returns Some
     crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
+        // FIXME: can we just pass `info` along rather than taking it apart here, only to have
+        // `rust_panic_with_hook` construct a new `PanicInfo`?
         if let Some(msg) = msg.as_str() {
-            rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind());
+            rust_panic_with_hook(
+                &mut StrPanicPayload(msg),
+                info.message(),
+                loc,
+                info.can_unwind(),
+                info.force_no_backtrace(),
+            );
         } else {
             rust_panic_with_hook(
                 &mut PanicPayload::new(msg),
                 info.message(),
                 loc,
                 info.can_unwind(),
+                info.force_no_backtrace(),
             );
         }
     })
@@ -647,7 +658,13 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
 
     let loc = Location::caller();
     return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
-        rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true)
+        rust_panic_with_hook(
+            &mut PanicPayload::new(msg),
+            None,
+            loc,
+            /* can_unwind */ true,
+            /* force_no_backtrace */ false,
+        )
     });
 
     struct PanicPayload<A> {
@@ -693,6 +710,7 @@ fn rust_panic_with_hook(
     message: Option<&fmt::Arguments<'_>>,
     location: &Location<'_>,
     can_unwind: bool,
+    force_no_backtrace: bool,
 ) -> ! {
     let must_abort = panic_count::increase(true);
 
@@ -707,14 +725,20 @@ fn rust_panic_with_hook(
             panic_count::MustAbort::AlwaysAbort => {
                 // Unfortunately, this does not print a backtrace, because creating
                 // a `Backtrace` will allocate, which we must to avoid here.
-                let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind);
+                let panicinfo = PanicInfo::internal_constructor(
+                    message,
+                    location,
+                    can_unwind,
+                    force_no_backtrace,
+                );
                 rtprintpanic!("{panicinfo}\npanicked after panic::always_abort(), aborting.\n");
             }
         }
         crate::sys::abort_internal();
     }
 
-    let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
+    let mut info =
+        PanicInfo::internal_constructor(message, location, can_unwind, force_no_backtrace);
     let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
     match *hook {
         // Some platforms (like wasm) know that printing to stderr won't ever actually
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 366b591466c..00636237288 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -434,6 +434,91 @@ fn test_creation_flags() {
     assert!(events > 0);
 }
 
+/// Tests proc thread attributes by spawning a process with a custom parent process,
+/// then comparing the parent process ID with the expected parent process ID.
+#[test]
+#[cfg(windows)]
+fn test_proc_thread_attributes() {
+    use crate::mem;
+    use crate::os::windows::io::AsRawHandle;
+    use crate::os::windows::process::CommandExt;
+    use crate::sys::c::{CloseHandle, BOOL, HANDLE};
+    use crate::sys::cvt;
+
+    #[repr(C)]
+    #[allow(non_snake_case)]
+    struct PROCESSENTRY32W {
+        dwSize: u32,
+        cntUsage: u32,
+        th32ProcessID: u32,
+        th32DefaultHeapID: usize,
+        th32ModuleID: u32,
+        cntThreads: u32,
+        th32ParentProcessID: u32,
+        pcPriClassBase: i32,
+        dwFlags: u32,
+        szExeFile: [u16; 260],
+    }
+
+    extern "system" {
+        fn CreateToolhelp32Snapshot(dwflags: u32, th32processid: u32) -> HANDLE;
+        fn Process32First(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+        fn Process32Next(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+    }
+
+    const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
+    const TH32CS_SNAPPROCESS: u32 = 0x00000002;
+
+    struct ProcessDropGuard(crate::process::Child);
+
+    impl Drop for ProcessDropGuard {
+        fn drop(&mut self) {
+            let _ = self.0.kill();
+        }
+    }
+
+    let parent = ProcessDropGuard(Command::new("cmd").spawn().unwrap());
+
+    let mut child_cmd = Command::new("cmd");
+
+    unsafe {
+        child_cmd
+            .raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize);
+    }
+
+    let child = ProcessDropGuard(child_cmd.spawn().unwrap());
+
+    let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
+
+    let mut process_entry = PROCESSENTRY32W {
+        dwSize: mem::size_of::<PROCESSENTRY32W>() as u32,
+        cntUsage: 0,
+        th32ProcessID: 0,
+        th32DefaultHeapID: 0,
+        th32ModuleID: 0,
+        cntThreads: 0,
+        th32ParentProcessID: 0,
+        pcPriClassBase: 0,
+        dwFlags: 0,
+        szExeFile: [0; 260],
+    };
+
+    unsafe { cvt(Process32First(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+
+    loop {
+        if child.0.id() == process_entry.th32ProcessID {
+            break;
+        }
+        unsafe { cvt(Process32Next(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+    }
+
+    unsafe { cvt(CloseHandle(h_snapshot)) }.unwrap();
+
+    assert_eq!(parent.0.id(), process_entry.th32ParentProcessID);
+
+    drop(child)
+}
+
 #[test]
 fn test_command_implements_send_sync() {
     fn take_send_sync_type<T: Send + Sync>(_: T) {}
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index c7cb8466705..fb22d3e22cd 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -101,7 +101,6 @@ pub extern "C" fn __rust_abort() {
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
 pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
-    let _ = net::init();
     args::init(argc, argv);
 }
 
diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs
index 8c2d489d6a3..bffda7a8139 100644
--- a/library/std/src/sys/hermit/net.rs
+++ b/library/std/src/sys/hermit/net.rs
@@ -33,13 +33,7 @@ pub fn cvt_gai(err: i32) -> io::Result<()> {
     ))
 }
 
-/// Checks whether the HermitCore's socket interface has been started already, and
-/// if not, starts it.
-pub fn init() {
-    if unsafe { netc::network_init() } < 0 {
-        panic!("Unable to initialize network interface");
-    }
-}
+pub fn init() {}
 
 #[derive(Debug)]
 pub struct Socket(FileDesc);
diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs
index 8604b53983d..af0089978ec 100644
--- a/library/std/src/sys/unix/alloc.rs
+++ b/library/std/src/sys/unix/alloc.rs
@@ -86,7 +86,11 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "wasi")] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-            libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
+            // C11 aligned_alloc requires that the size be a multiple of the alignment.
+            // Layout already checks that the size rounded up doesn't overflow isize::MAX.
+            let align = layout.align();
+            let size = layout.size().next_multiple_of(align);
+            libc::aligned_alloc(align, size) as *mut u8
         }
     } else {
         #[inline]
diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst
index 631aedd26b4..5469ba42eb1 100644
--- a/library/std/src/sys/windows/c/windows_sys.lst
+++ b/library/std/src/sys/windows/c/windows_sys.lst
@@ -2510,6 +2510,7 @@ Windows.Win32.System.Threading.CreateProcessW
 Windows.Win32.System.Threading.CreateThread
 Windows.Win32.System.Threading.DEBUG_ONLY_THIS_PROCESS
 Windows.Win32.System.Threading.DEBUG_PROCESS
+Windows.Win32.System.Threading.DeleteProcThreadAttributeList
 Windows.Win32.System.Threading.DETACHED_PROCESS
 Windows.Win32.System.Threading.ExitProcess
 Windows.Win32.System.Threading.EXTENDED_STARTUPINFO_PRESENT
@@ -2524,8 +2525,10 @@ Windows.Win32.System.Threading.INFINITE
 Windows.Win32.System.Threading.INHERIT_CALLER_PRIORITY
 Windows.Win32.System.Threading.INHERIT_PARENT_AFFINITY
 Windows.Win32.System.Threading.INIT_ONCE_INIT_FAILED
+Windows.Win32.System.Threading.InitializeProcThreadAttributeList
 Windows.Win32.System.Threading.InitOnceBeginInitialize
 Windows.Win32.System.Threading.InitOnceComplete
+Windows.Win32.System.Threading.LPPROC_THREAD_ATTRIBUTE_LIST
 Windows.Win32.System.Threading.LPTHREAD_START_ROUTINE
 Windows.Win32.System.Threading.NORMAL_PRIORITY_CLASS
 Windows.Win32.System.Threading.OpenProcessToken
@@ -2561,6 +2564,7 @@ Windows.Win32.System.Threading.STARTF_USEPOSITION
 Windows.Win32.System.Threading.STARTF_USESHOWWINDOW
 Windows.Win32.System.Threading.STARTF_USESIZE
 Windows.Win32.System.Threading.STARTF_USESTDHANDLES
+Windows.Win32.System.Threading.STARTUPINFOEXW
 Windows.Win32.System.Threading.STARTUPINFOW
 Windows.Win32.System.Threading.STARTUPINFOW_FLAGS
 Windows.Win32.System.Threading.SwitchToThread
@@ -2575,6 +2579,7 @@ Windows.Win32.System.Threading.TlsGetValue
 Windows.Win32.System.Threading.TlsSetValue
 Windows.Win32.System.Threading.TryAcquireSRWLockExclusive
 Windows.Win32.System.Threading.TryAcquireSRWLockShared
+Windows.Win32.System.Threading.UpdateProcThreadAttribute
 Windows.Win32.System.Threading.WaitForMultipleObjects
 Windows.Win32.System.Threading.WaitForSingleObject
 Windows.Win32.System.Threading.WakeAllConditionVariable
diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs
index 02377087173..b24f6dc900f 100644
--- a/library/std/src/sys/windows/c/windows_sys.rs
+++ b/library/std/src/sys/windows/c/windows_sys.rs
@@ -156,6 +156,10 @@ extern "system" {
 }
 #[link(name = "kernel32")]
 extern "system" {
+    pub fn DeleteProcThreadAttributeList(lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST) -> ();
+}
+#[link(name = "kernel32")]
+extern "system" {
     pub fn DeviceIoControl(
         hdevice: HANDLE,
         dwiocontrolcode: u32,
@@ -372,6 +376,15 @@ extern "system" {
 }
 #[link(name = "kernel32")]
 extern "system" {
+    pub fn InitializeProcThreadAttributeList(
+        lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST,
+        dwattributecount: u32,
+        dwflags: u32,
+        lpsize: *mut usize,
+    ) -> BOOL;
+}
+#[link(name = "kernel32")]
+extern "system" {
     pub fn MoveFileExW(
         lpexistingfilename: PCWSTR,
         lpnewfilename: PCWSTR,
@@ -544,6 +557,18 @@ extern "system" {
 }
 #[link(name = "kernel32")]
 extern "system" {
+    pub fn UpdateProcThreadAttribute(
+        lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST,
+        dwflags: u32,
+        attribute: usize,
+        lpvalue: *const ::core::ffi::c_void,
+        cbsize: usize,
+        lppreviousvalue: *mut ::core::ffi::c_void,
+        lpreturnsize: *const usize,
+    ) -> BOOL;
+}
+#[link(name = "kernel32")]
+extern "system" {
     pub fn WaitForMultipleObjects(
         ncount: u32,
         lphandles: *const HANDLE,
@@ -3567,6 +3592,7 @@ pub type LPOVERLAPPED_COMPLETION_ROUTINE = ::core::option::Option<
         lpoverlapped: *mut OVERLAPPED,
     ) -> (),
 >;
+pub type LPPROC_THREAD_ATTRIBUTE_LIST = *mut ::core::ffi::c_void;
 pub type LPPROGRESS_ROUTINE = ::core::option::Option<
     unsafe extern "system" fn(
         totalfilesize: i64,
@@ -3833,6 +3859,17 @@ pub const STARTF_USESHOWWINDOW: STARTUPINFOW_FLAGS = 1u32;
 pub const STARTF_USESIZE: STARTUPINFOW_FLAGS = 2u32;
 pub const STARTF_USESTDHANDLES: STARTUPINFOW_FLAGS = 256u32;
 #[repr(C)]
+pub struct STARTUPINFOEXW {
+    pub StartupInfo: STARTUPINFOW,
+    pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST,
+}
+impl ::core::marker::Copy for STARTUPINFOEXW {}
+impl ::core::clone::Clone for STARTUPINFOEXW {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+#[repr(C)]
 pub struct STARTUPINFOW {
     pub cb: u32,
     pub lpReserved: PWSTR,
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 2dd0c67acdb..92edd2f6112 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -11,6 +11,7 @@ use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::mem;
+use crate::mem::MaybeUninit;
 use crate::num::NonZeroI32;
 use crate::os::windows::ffi::{OsStrExt, OsStringExt};
 use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle};
@@ -166,6 +167,7 @@ pub struct Command {
     stdout: Option<Stdio>,
     stderr: Option<Stdio>,
     force_quotes_enabled: bool,
+    proc_thread_attributes: BTreeMap<usize, ProcThreadAttributeValue>,
 }
 
 pub enum Stdio {
@@ -195,6 +197,7 @@ impl Command {
             stdout: None,
             stderr: None,
             force_quotes_enabled: false,
+            proc_thread_attributes: Default::default(),
         }
     }
 
@@ -245,6 +248,17 @@ impl Command {
         self.cwd.as_ref().map(|cwd| Path::new(cwd))
     }
 
+    pub unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>(
+        &mut self,
+        attribute: usize,
+        value: T,
+    ) {
+        self.proc_thread_attributes.insert(
+            attribute,
+            ProcThreadAttributeValue { size: mem::size_of::<T>(), data: Box::new(value) },
+        );
+    }
+
     pub fn spawn(
         &mut self,
         default: Stdio,
@@ -308,7 +322,6 @@ impl Command {
         let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
 
         let mut si = zeroed_startupinfo();
-        si.cb = mem::size_of::<c::STARTUPINFOW>() as c::DWORD;
 
         // If at least one of stdin, stdout or stderr are set (i.e. are non null)
         // then set the `hStd` fields in `STARTUPINFO`.
@@ -322,6 +335,27 @@ impl Command {
             si.hStdError = stderr.as_raw_handle();
         }
 
+        let si_ptr: *mut c::STARTUPINFOW;
+
+        let mut proc_thread_attribute_list;
+        let mut si_ex;
+
+        if !self.proc_thread_attributes.is_empty() {
+            si.cb = mem::size_of::<c::STARTUPINFOEXW>() as u32;
+            flags |= c::EXTENDED_STARTUPINFO_PRESENT;
+
+            proc_thread_attribute_list =
+                make_proc_thread_attribute_list(&self.proc_thread_attributes)?;
+            si_ex = c::STARTUPINFOEXW {
+                StartupInfo: si,
+                lpAttributeList: proc_thread_attribute_list.0.as_mut_ptr() as _,
+            };
+            si_ptr = &mut si_ex as *mut _ as _;
+        } else {
+            si.cb = mem::size_of::<c::STARTUPINFOW> as c::DWORD;
+            si_ptr = &mut si as *mut _ as _;
+        }
+
         unsafe {
             cvt(c::CreateProcessW(
                 program.as_ptr(),
@@ -332,7 +366,7 @@ impl Command {
                 flags,
                 envp,
                 dirp,
-                &si,
+                si_ptr,
                 &mut pi,
             ))
         }?;
@@ -831,6 +865,80 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> {
     }
 }
 
+struct ProcThreadAttributeList(Box<[MaybeUninit<u8>]>);
+
+impl Drop for ProcThreadAttributeList {
+    fn drop(&mut self) {
+        let lp_attribute_list = self.0.as_mut_ptr() as _;
+        unsafe { c::DeleteProcThreadAttributeList(lp_attribute_list) }
+    }
+}
+
+/// Wrapper around the value data to be used as a Process Thread Attribute.
+struct ProcThreadAttributeValue {
+    data: Box<dyn Send + Sync>,
+    size: usize,
+}
+
+fn make_proc_thread_attribute_list(
+    attributes: &BTreeMap<usize, ProcThreadAttributeValue>,
+) -> io::Result<ProcThreadAttributeList> {
+    // To initialize our ProcThreadAttributeList, we need to determine
+    // how many bytes to allocate for it. The Windows API simplifies this process
+    // by allowing us to call `InitializeProcThreadAttributeList` with
+    // a null pointer to retrieve the required size.
+    let mut required_size = 0;
+    let Ok(attribute_count) = attributes.len().try_into() else {
+        return Err(io::const_io_error!(
+            ErrorKind::InvalidInput,
+            "maximum number of ProcThreadAttributes exceeded",
+        ));
+    };
+    unsafe {
+        c::InitializeProcThreadAttributeList(
+            ptr::null_mut(),
+            attribute_count,
+            0,
+            &mut required_size,
+        )
+    };
+
+    let mut proc_thread_attribute_list = ProcThreadAttributeList(
+        vec![MaybeUninit::uninit(); required_size as usize].into_boxed_slice(),
+    );
+
+    // Once we've allocated the necessary memory, it's safe to invoke
+    // `InitializeProcThreadAttributeList` to properly initialize the list.
+    cvt(unsafe {
+        c::InitializeProcThreadAttributeList(
+            proc_thread_attribute_list.0.as_mut_ptr() as *mut _,
+            attribute_count,
+            0,
+            &mut required_size,
+        )
+    })?;
+
+    // # Add our attributes to the buffer.
+    // It's theoretically possible for the attribute count to exceed a u32 value.
+    // Therefore, we ensure that we don't add more attributes than the buffer was initialized for.
+    for (&attribute, value) in attributes.iter().take(attribute_count as usize) {
+        let value_ptr = &*value.data as *const (dyn Send + Sync) as _;
+        cvt(unsafe {
+            c::UpdateProcThreadAttribute(
+                proc_thread_attribute_list.0.as_mut_ptr() as _,
+                0,
+                attribute,
+                value_ptr,
+                value.size,
+                ptr::null_mut(),
+                ptr::null_mut(),
+            )
+        })?;
+    }
+
+    Ok(proc_thread_attribute_list)
+}
+
 pub struct CommandArgs<'a> {
     iter: crate::slice::Iter<'a, Arg>,
 }
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 00e2857a137..c638cc61856 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -176,6 +176,14 @@ pub struct Instant(time::Instant);
 /// The size of a `SystemTime` struct may vary depending on the target operating
 /// system.
 ///
+/// A `SystemTime` does not count leap seconds.
+/// `SystemTime::now()`'s behaviour around a leap second
+/// is the same as the operating system's wall clock.
+/// The precise behaviour near a leap second
+/// (e.g. whether the clock appears to run slow or fast, or stop, or jump)
+/// depends on platform and configuration,
+/// so should not be relied on.
+///
 /// Example:
 ///
 /// ```no_run
@@ -461,6 +469,9 @@ impl fmt::Debug for Instant {
 impl SystemTime {
     /// An anchor in time which can be used to create new `SystemTime` instances or
     /// learn about where in time a `SystemTime` lies.
+    //
+    // NOTE! this documentation is duplicated, here and in std::time::UNIX_EPOCH.
+    // The two copies are not quite identical, because of the difference in naming.
     ///
     /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
     /// respect to the system clock. Using `duration_since` on an existing
@@ -468,6 +479,11 @@ impl SystemTime {
     /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
     /// `SystemTime` instance to represent another fixed point in time.
     ///
+    /// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns
+    /// the number of non-leap seconds since the start of 1970 UTC.
+    /// This is a POSIX `time_t` (as a `u64`),
+    /// and is the same time representation as used in many Internet protocols.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -617,6 +633,9 @@ impl fmt::Debug for SystemTime {
 
 /// An anchor in time which can be used to create new `SystemTime` instances or
 /// learn about where in time a `SystemTime` lies.
+//
+// NOTE! this documentation is duplicated, here and in SystemTime::UNIX_EPOCH.
+// The two copies are not quite identical, because of the difference in naming.
 ///
 /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
 /// respect to the system clock. Using `duration_since` on an existing
@@ -624,6 +643,11 @@ impl fmt::Debug for SystemTime {
 /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
 /// [`SystemTime`] instance to represent another fixed point in time.
 ///
+/// `duration_since(UNIX_EPOCH).unwrap().as_secs()` returns
+/// the number of non-leap seconds since the start of 1970 UTC.
+/// This is a POSIX `time_t` (as a `u64`),
+/// and is the same time representation as used in many Internet protocols.
+///
 /// # Examples
 ///
 /// ```no_run