about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/collections/hash/map.rs7
-rw-r--r--library/std/src/collections/hash/set.rs4
-rw-r--r--library/std/src/f32.rs20
-rw-r--r--library/std/src/f64.rs46
-rw-r--r--library/std/src/ffi/c_str.rs3
-rw-r--r--library/std/src/fs/tests.rs3
-rw-r--r--library/std/src/io/buffered/bufwriter.rs2
-rw-r--r--library/std/src/io/impls.rs6
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--library/std/src/io/stdio.rs38
-rw-r--r--library/std/src/keyword_docs.rs24
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/macros.rs7
-rw-r--r--library/std/src/net/addr/tests.rs2
-rw-r--r--library/std/src/net/ip.rs13
-rw-r--r--library/std/src/net/udp/tests.rs14
-rw-r--r--library/std/src/panic.rs14
-rw-r--r--library/std/src/panicking.rs20
-rw-r--r--library/std/src/path.rs11
-rw-r--r--library/std/src/process.rs12
-rw-r--r--library/std/src/sys/cloudabi/abi/cloudabi.rs133
-rw-r--r--library/std/src/sys/cloudabi/mod.rs2
-rw-r--r--library/std/src/sys/cloudabi/mutex.rs4
-rw-r--r--library/std/src/sys/hermit/fs.rs4
-rw-r--r--library/std/src/sys/hermit/mod.rs1
-rw-r--r--library/std/src/sys/hermit/mutex.rs190
-rw-r--r--library/std/src/sys/hermit/process.rs149
-rw-r--r--library/std/src/sys/mod.rs1
-rw-r--r--library/std/src/sys/sgx/env.rs14
-rw-r--r--library/std/src/sys/sgx/path.rs2
-rw-r--r--library/std/src/sys/unix/mod.rs4
-rw-r--r--library/std/src/sys/unix/mutex.rs39
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs6
-rw-r--r--library/std/src/sys/unix/thread.rs3
-rw-r--r--library/std/src/sys/wasm/alloc.rs16
-rw-r--r--library/std/src/sys/wasm/condvar_atomics.rs10
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/wasm/mutex_atomics.rs25
-rw-r--r--library/std/src/thread/mod.rs5
39 files changed, 501 insertions, 361 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 114707b639b..d1244c2ca53 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -606,7 +606,7 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid
+    /// in the given `HashMap<K, V>`. The collection may reserve more space to avoid
     /// frequent reallocations.
     ///
     /// # Errors
@@ -619,6 +619,7 @@ where
     /// ```
     /// #![feature(try_reserve)]
     /// use std::collections::HashMap;
+    ///
     /// let mut map: HashMap<&str, isize> = HashMap::new();
     /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
     /// ```
@@ -898,14 +899,14 @@ where
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
+    /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`.
     ///
     /// # Examples
     ///
     /// ```
     /// use std::collections::HashMap;
     ///
-    /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
+    /// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x*10)).collect();
     /// map.retain(|&k, _| k % 2 == 0);
     /// assert_eq!(map.len(), 4);
     /// ```
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index a0c39852ad5..3299fd12e02 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -412,7 +412,7 @@ where
     }
 
     /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashSet<K,V>`. The collection may reserve more space to avoid
+    /// in the given `HashSet<K, V>`. The collection may reserve more space to avoid
     /// frequent reallocations.
     ///
     /// # Errors
@@ -918,7 +918,7 @@ where
     /// ```
     /// use std::collections::HashSet;
     ///
-    /// let xs = [1,2,3,4,5,6];
+    /// let xs = [1, 2, 3, 4, 5, 6];
     /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
     /// set.retain(|&k| k % 2 == 0);
     /// assert_eq!(set.len(), 3);
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 59c2da5273b..2a54b117ff4 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -1,7 +1,7 @@
 //! This module provides constants which are specific to the implementation
 //! of the `f32` floating point data type.
 //!
-//! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
+//! *[See also the `f32` primitive type](primitive@f32).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
@@ -719,12 +719,13 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// let x = 6.0f32;
+    /// let x = 1e-8_f32;
     ///
-    /// // e^(ln(6)) - 1
-    /// let abs_difference = (x.ln().exp_m1() - 5.0).abs();
+    /// // for very small x, e^x is approximately 1 + x + x^2 / 2
+    /// let approx = x + x * x / 2.0;
+    /// let abs_difference = (x.exp_m1() - approx).abs();
     ///
-    /// assert!(abs_difference <= f32::EPSILON);
+    /// assert!(abs_difference < 1e-10);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -739,12 +740,13 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// let x = std::f32::consts::E - 1.0;
+    /// let x = 1e-8_f32;
     ///
-    /// // ln(1 + (e - 1)) == ln(e) == 1
-    /// let abs_difference = (x.ln_1p() - 1.0).abs();
+    /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
+    /// let approx = x - x * x / 2.0;
+    /// let abs_difference = (x.ln_1p() - approx).abs();
     ///
-    /// assert!(abs_difference <= f32::EPSILON);
+    /// assert!(abs_difference < 1e-10);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index bd094bdb55d..363d1a00476 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -1,7 +1,7 @@
 //! This module provides constants which are specific to the implementation
 //! of the `f64` floating point data type.
 //!
-//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
+//! *[See also the `f64` primitive type](primitive@f64).*
 //!
 //! Mathematically significant numbers are provided in the `consts` sub-module.
 //!
@@ -721,12 +721,13 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// let x = 7.0_f64;
+    /// let x = 1e-16_f64;
     ///
-    /// // e^(ln(7)) - 1
-    /// let abs_difference = (x.ln().exp_m1() - 6.0).abs();
+    /// // for very small x, e^x is approximately 1 + x + x^2 / 2
+    /// let approx = x + x * x / 2.0;
+    /// let abs_difference = (x.exp_m1() - approx).abs();
     ///
-    /// assert!(abs_difference < 1e-10);
+    /// assert!(abs_difference < 1e-20);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -741,12 +742,13 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// let x = std::f64::consts::E - 1.0;
+    /// let x = 1e-16_f64;
     ///
-    /// // ln(1 + (e - 1)) == ln(e) == 1
-    /// let abs_difference = (x.ln_1p() - 1.0).abs();
+    /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
+    /// let approx = x - x * x / 2.0;
+    /// let abs_difference = (x.ln_1p() - approx).abs();
     ///
-    /// assert!(abs_difference < 1e-10);
+    /// assert!(abs_difference < 1e-20);
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -920,22 +922,20 @@ impl f64 {
     fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
         if !cfg!(any(target_os = "solaris", target_os = "illumos")) {
             log_fn(self)
-        } else {
-            if self.is_finite() {
-                if self > 0.0 {
-                    log_fn(self)
-                } else if self == 0.0 {
-                    Self::NEG_INFINITY // log(0) = -Inf
-                } else {
-                    Self::NAN // log(-n) = NaN
-                }
-            } else if self.is_nan() {
-                self // log(NaN) = NaN
-            } else if self > 0.0 {
-                self // log(Inf) = Inf
+        } else if self.is_finite() {
+            if self > 0.0 {
+                log_fn(self)
+            } else if self == 0.0 {
+                Self::NEG_INFINITY // log(0) = -Inf
             } else {
-                Self::NAN // log(-Inf) = NaN
+                Self::NAN // log(-n) = NaN
             }
+        } else if self.is_nan() {
+            self // log(NaN) = NaN
+        } else if self > 0.0 {
+            self // log(Inf) = Inf
+        } else {
+            Self::NAN // log(-Inf) = NaN
         }
     }
 }
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 6df4eb99259..8c6d6c80402 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -110,6 +110,7 @@ use crate::sys;
 /// of `CString` instances can lead to invalid memory accesses, memory leaks,
 /// and other memory errors.
 #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CString {
     // Invariant 1: the slice ends with a zero byte and has a length of at least one.
@@ -1265,7 +1266,7 @@ impl CStr {
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
-    /// # #![allow(unused_must_use)]
+    /// # #![allow(unused_must_use)] #![cfg_attr(not(bootstrap), allow(temporary_cstring_as_ptr))]
     /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 65a29076fef..38fd470a1c3 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -73,10 +73,9 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
     let link = tmpdir.join("some_hopefully_unique_link_name");
 
     match symlink_file(r"nonexisting_target", link) {
-        Ok(_) => true,
         // ERROR_PRIVILEGE_NOT_HELD = 1314
         Err(ref err) if err.raw_os_error() == Some(1314) => false,
-        Err(_) => true,
+        Ok(_) | Err(_) => true,
     }
 }
 
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 8ce795a05ed..3ec272fea66 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -15,7 +15,7 @@ use crate::io::{
 /// *repeated* write calls to the same file or network socket. It does not
 /// help when writing very large amounts at once, or writing just one or a few
 /// times. It also provides no advantage when writing to a destination that is
-/// in memory, like a [`Vec`]<u8>`.
+/// in memory, like a [`Vec`]`<u8>`.
 ///
 /// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
 /// dropping will attempt to flush the contents of the buffer, any errors
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index e09e7ba978e..66426101d27 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -213,13 +213,13 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> {
 #[cfg(test)]
 /// This impl is only used by printing logic, so any error returned is always
 /// of kind `Other`, and should be ignored.
-impl Write for Box<dyn (::realstd::io::Write) + Send> {
+impl Write for dyn ::realstd::io::LocalOutput {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        (**self).write(buf).map_err(|_| ErrorKind::Other.into())
+        (*self).write(buf).map_err(|_| ErrorKind::Other.into())
     }
 
     fn flush(&mut self) -> io::Result<()> {
-        (**self).flush().map_err(|_| ErrorKind::Other.into())
+        (*self).flush().map_err(|_| ErrorKind::Other.into())
     }
 }
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index d9d03807819..e6efe6ec57e 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -277,10 +277,12 @@ pub use self::stdio::{StderrLock, StdinLock, StdoutLock};
 pub use self::stdio::{_eprint, _print};
 #[unstable(feature = "libstd_io_internals", issue = "42788")]
 #[doc(no_inline, hidden)]
-pub use self::stdio::{set_panic, set_print};
+pub use self::stdio::{set_panic, set_print, LocalOutput};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::util::{copy, empty, repeat, sink, Empty, Repeat, Sink};
 
+pub(crate) use self::stdio::clone_io;
+
 mod buffered;
 mod cursor;
 mod error;
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 36b49401591..2eb5fb45286 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -18,14 +18,14 @@ use crate::thread::LocalKey;
 
 thread_local! {
     /// Used by the test crate to capture the output of the print! and println! macros.
-    static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
+    static LOCAL_STDOUT: RefCell<Option<Box<dyn LocalOutput>>> = {
         RefCell::new(None)
     }
 }
 
 thread_local! {
     /// Used by the test crate to capture the output of the eprint! and eprintln! macros, and panics.
-    static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
+    static LOCAL_STDERR: RefCell<Option<Box<dyn LocalOutput>>> = {
         RefCell::new(None)
     }
 }
@@ -888,6 +888,18 @@ impl fmt::Debug for StderrLock<'_> {
     }
 }
 
+/// A writer than can be cloned to new threads.
+#[unstable(
+    feature = "set_stdio",
+    reason = "this trait may disappear completely or be replaced \
+                     with a more general mechanism",
+    issue = "none"
+)]
+#[doc(hidden)]
+pub trait LocalOutput: Write + Send {
+    fn clone_box(&self) -> Box<dyn LocalOutput>;
+}
+
 /// Resets the thread-local stderr handle to the specified writer
 ///
 /// This will replace the current thread's stderr handle, returning the old
@@ -903,7 +915,7 @@ impl fmt::Debug for StderrLock<'_> {
     issue = "none"
 )]
 #[doc(hidden)]
-pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
+pub fn set_panic(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutput>> {
     use crate::mem;
     if sink.is_none() && !LOCAL_STREAMS.load(Ordering::Relaxed) {
         // LOCAL_STDERR is definitely None since LOCAL_STREAMS is false.
@@ -934,7 +946,7 @@ pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
     issue = "none"
 )]
 #[doc(hidden)]
-pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
+pub fn set_print(sink: Option<Box<dyn LocalOutput>>) -> Option<Box<dyn LocalOutput>> {
     use crate::mem;
     if sink.is_none() && !LOCAL_STREAMS.load(Ordering::Relaxed) {
         // LOCAL_STDOUT is definitely None since LOCAL_STREAMS is false.
@@ -950,6 +962,22 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
     s
 }
 
+pub(crate) fn clone_io() -> (Option<Box<dyn LocalOutput>>, Option<Box<dyn LocalOutput>>) {
+    // Don't waste time when LOCAL_{STDOUT,STDERR} are definitely None.
+    if !LOCAL_STREAMS.load(Ordering::Relaxed) {
+        return (None, None);
+    }
+
+    LOCAL_STDOUT.with(|stdout| {
+        LOCAL_STDERR.with(|stderr| {
+            (
+                stdout.borrow().as_ref().map(|o| o.clone_box()),
+                stderr.borrow().as_ref().map(|o| o.clone_box()),
+            )
+        })
+    })
+}
+
 /// Write `args` to output stream `local_s` if possible, `global_s`
 /// otherwise. `label` identifies the stream in a panic message.
 ///
@@ -962,7 +990,7 @@ pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write +
 /// However, if the actual I/O causes an error, this function does panic.
 fn print_to<T>(
     args: fmt::Arguments<'_>,
-    local_s: &'static LocalKey<RefCell<Option<Box<dyn Write + Send>>>>,
+    local_s: &'static LocalKey<RefCell<Option<Box<dyn LocalOutput>>>>,
     global_s: fn() -> T,
     label: &str,
 ) where
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 54ce0e7b831..9b704ee9eca 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -102,7 +102,9 @@ mod break_keyword {}
 
 #[doc(keyword = "const")]
 //
-/// Compile-time constants and deterministic functions.
+/// Compile-time constants and compile-time evaluable functions.
+///
+/// ## Compile-time constants
 ///
 /// Sometimes a certain value is used many times throughout a program, and it can become
 /// inconvenient to copy it over and over. What's more, it's not always possible or desirable to
@@ -145,15 +147,28 @@ mod break_keyword {}
 ///
 /// Constants, like statics, should always be in `SCREAMING_SNAKE_CASE`.
 ///
+/// For more detail on `const`, see the [Rust Book] or the [Reference].
+///
+/// ## Compile-time evaluable functions
+///
+/// The other main use of the `const` keyword is in `const fn`. This marks a function as being
+/// callable in the body of a `const` or `static` item and in array initializers (commonly called
+/// "const contexts"). `const fn` are restricted in the set of operations they can perform, to
+/// ensure that they can be evaluated at compile-time. See the [Reference][const-eval] for more
+/// detail.
+///
+/// Turning a `fn` into a `const fn` has no effect on run-time uses of that function.
+///
+/// ## Other uses of `const`
+///
 /// The `const` keyword is also used in raw pointers in combination with `mut`, as seen in `*const
 /// T` and `*mut T`. More about `const` as used in raw pointers can be read at the Rust docs for the [pointer primitive].
 ///
-/// For more detail on `const`, see the [Rust Book] or the [Reference].
-///
 /// [pointer primitive]: primitive.pointer.html
 /// [Rust Book]:
 /// ../book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
 /// [Reference]: ../reference/items/constant-items.html
+/// [const-eval]: ../reference/const_eval.html
 mod const_keyword {}
 
 #[doc(keyword = "continue")]
@@ -331,7 +346,7 @@ mod else_keyword {}
 /// When data follows along with a variant, such as with rust's built-in [`Option`] type, the data
 /// is added as the type describes, for example `Option::Some(123)`. The same follows with
 /// struct-like variants, with things looking like `ComplexEnum::LotsOfThings { usual_struct_stuff:
-/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to () in that they cannot be
+/// true, blah: "hello!".to_string(), }`. Empty Enums are similar to [`!`] in that they cannot be
 /// instantiated at all, and are used mainly to mess with the type system in interesting ways.
 ///
 /// For more information, take a look at the [Rust Book] or the [Reference]
@@ -339,6 +354,7 @@ mod else_keyword {}
 /// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type
 /// [Rust Book]: ../book/ch06-01-defining-an-enum.html
 /// [Reference]: ../reference/items/enumerations.html
+/// [`!`]: primitive.never.html
 mod enum_keyword {}
 
 #[doc(keyword = "extern")]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 30e7a7f3c3b..96a7755c688 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -206,6 +206,7 @@
 #![needs_panic_runtime]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
 #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
@@ -259,6 +260,7 @@
 #![feature(exhaustive_patterns)]
 #![feature(extend_one)]
 #![feature(external_doc)]
+#![feature(fmt_as_str)]
 #![feature(fn_traits)]
 #![feature(format_args_nl)]
 #![feature(gen_future)]
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index e8898d98ff3..57649d6f8f2 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -10,8 +10,7 @@
 #[allow_internal_unstable(libstd_sys_internals)]
 macro_rules! panic {
     () => ({ $crate::panic!("explicit panic") });
-    ($msg:expr) => ({ $crate::rt::begin_panic($msg) });
-    ($msg:expr,) => ({ $crate::panic!($msg) });
+    ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) });
     ($fmt:expr, $($arg:tt)+) => ({
         $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+))
     });
@@ -285,7 +284,7 @@ macro_rules! dbg {
     () => {
         $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
     };
-    ($val:expr) => {
+    ($val:expr $(,)?) => {
         // Use of `match` here is intentional because it affects the lifetimes
         // of temporaries - https://stackoverflow.com/a/48732525/1063961
         match $val {
@@ -296,8 +295,6 @@ macro_rules! dbg {
             }
         }
     };
-    // Trailing comma with single argument is ignored
-    ($val:expr,) => { $crate::dbg!($val) };
     ($($val:expr),+ $(,)?) => {
         ($($crate::dbg!($val)),+,)
     };
diff --git a/library/std/src/net/addr/tests.rs b/library/std/src/net/addr/tests.rs
index 43f965de25e..40f5a84bcd5 100644
--- a/library/std/src/net/addr/tests.rs
+++ b/library/std/src/net/addr/tests.rs
@@ -68,7 +68,7 @@ fn bind_udp_socket_bad() {
     // returns its own address, it is still an error to bind a UDP socket to
     // a non-local address, and so we still get an error here in that case.
 
-    const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300";
+    const INPUT_23076: &str = "1200::AB00:1234::2552:7777:1313:34300";
 
     assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err())
 }
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index f01a7b72a65..bb3ece4c273 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -456,10 +456,7 @@ impl Ipv4Addr {
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[stable(since = "1.7.0", feature = "ip_17")]
     pub const fn is_link_local(&self) -> bool {
-        match self.octets() {
-            [169, 254, ..] => true,
-            _ => false,
-        }
+        matches!(self.octets(), [169, 254, ..])
     }
 
     /// Returns [`true`] if the address appears to be globally routable.
@@ -1046,7 +1043,8 @@ impl Ipv6Addr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
-    #[allow_internal_unstable(const_fn_transmute)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         let addr16 = [
             a.to_be(),
@@ -1262,10 +1260,7 @@ impl Ipv6Addr {
     /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
     pub const fn is_unicast_link_local_strict(&self) -> bool {
-        (self.segments()[0] & 0xffff) == 0xfe80
-            && (self.segments()[1] & 0xffff) == 0
-            && (self.segments()[2] & 0xffff) == 0
-            && (self.segments()[3] & 0xffff) == 0
+        matches!(self.segments(), [0xfe80, 0, 0, 0, ..])
     }
 
     /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index 658369f79aa..fbed3d32d45 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -152,19 +152,13 @@ fn udp_clone_two_write() {
         let (done, rx) = channel();
         let tx2 = tx.clone();
         let _t = thread::spawn(move || {
-            match sock3.send_to(&[1], &addr2) {
-                Ok(..) => {
-                    let _ = tx2.send(());
-                }
-                Err(..) => {}
+            if sock3.send_to(&[1], &addr2).is_ok() {
+                let _ = tx2.send(());
             }
             done.send(()).unwrap();
         });
-        match sock1.send_to(&[2], &addr2) {
-            Ok(..) => {
-                let _ = tx.send(());
-            }
-            Err(..) => {}
+        if sock1.send_to(&[2], &addr2).is_ok() {
+            let _ = tx.send(());
         }
         drop(tx);
 
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 4281867314c..d18b94b6c1a 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -23,6 +23,20 @@ pub use crate::panicking::{set_hook, take_hook};
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub use core::panic::{Location, PanicInfo};
 
+/// Panic the current thread with the given message as the panic payload.
+///
+/// The message can be of any (`Any + Send`) type, not just strings.
+///
+/// The message is wrapped in a `Box<'static + Any + Send>`, which can be
+/// accessed later using [`PanicInfo::payload`].
+///
+/// See the [`panic!`] macro for more information about panicking.
+#[unstable(feature = "panic_any", issue = "78500")]
+#[inline]
+pub fn panic_any<M: Any + Send>(msg: M) -> ! {
+    crate::panicking::begin_panic(msg);
+}
+
 /// A marker trait which represents "panic safe" types in Rust.
 ///
 /// This trait is implemented by default for many types and behaves similarly in
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 8dceb12de87..fbbc61f4e60 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -220,7 +220,7 @@ fn default_hook(info: &PanicInfo<'_>) {
 
     if let Some(mut local) = set_panic(None) {
         // NB. In `cfg(test)` this uses the forwarding impl
-        // for `Box<dyn (::realstd::io::Write) + Send>`.
+        // for `dyn ::realstd::io::LocalOutput`.
         write(&mut local);
         set_panic(Some(local));
     } else if let Some(mut out) = panic_output() {
@@ -478,10 +478,26 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
         }
     }
 
+    struct StrPanicPayload(&'static str);
+
+    unsafe impl BoxMeUp for StrPanicPayload {
+        fn take_box(&mut self) -> *mut (dyn Any + Send) {
+            Box::into_raw(Box::new(self.0))
+        }
+
+        fn get(&mut self) -> &(dyn Any + Send) {
+            &self.0
+        }
+    }
+
     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 || {
-        rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
+        if let Some(msg) = msg.as_str() {
+            rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc);
+        } else {
+            rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
+        }
     })
 }
 
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 50bd2a03b62..8a75c1d6058 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -446,7 +446,7 @@ impl Hash for PrefixComponent<'_> {
 /// (`/` or `\`).
 ///
 /// This `enum` is created by iterating over [`Components`], which in turn is
-/// created by the [`components`][`Path::components`] method on [`Path`].
+/// created by the [`components`](Path::components) method on [`Path`].
 ///
 /// # Examples
 ///
@@ -1319,7 +1319,7 @@ impl PathBuf {
         self.inner
     }
 
-    /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`].
+    /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_boxed_path(self) -> Box<Path> {
         let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
@@ -1686,8 +1686,7 @@ pub struct Path {
     inner: OsStr,
 }
 
-/// An error returned from [`Path::strip_prefix`][`strip_prefix`] if the prefix
-/// was not found.
+/// An error returned from [`Path::strip_prefix`] if the prefix was not found.
 ///
 /// This `struct` is created by the [`strip_prefix`] method on [`Path`].
 /// See its documentation for more.
@@ -2470,7 +2469,7 @@ impl Path {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
-    /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
+    /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     pub fn into_path_buf(self: Box<Path>) -> PathBuf {
@@ -2498,7 +2497,7 @@ impl fmt::Debug for Path {
 ///
 /// A [`Path`] might contain non-Unicode data. This `struct` implements the
 /// [`Display`] trait in a way that mitigates that. It is created by the
-/// [`display`][`Path::display`] method on [`Path`].
+/// [`display`](Path::display) method on [`Path`].
 ///
 /// # Examples
 ///
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 3d238b7f764..2c7ed4614bc 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -557,6 +557,11 @@ impl Command {
     ///
     /// [`args`]: Command::args
     ///
+    /// Note that the argument is not passed through a shell, but given
+    /// literally to the program. This means that shell syntax like quotes,
+    /// escaped characters, word splitting, glob patterns, substitution, etc.
+    /// have no effect.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -582,6 +587,11 @@ impl Command {
     ///
     /// [`arg`]: Command::arg
     ///
+    /// Note that the arguments are not passed through a shell, but given
+    /// literally to the program. This means that shell syntax like quotes,
+    /// escaped characters, word splitting, glob patterns, substitution, etc.
+    /// have no effect.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1184,7 +1194,7 @@ impl Stdio {
     }
 
     /// This stream will be ignored. This is the equivalent of attaching the
-    /// stream to `/dev/null`
+    /// stream to `/dev/null`.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sys/cloudabi/abi/cloudabi.rs b/library/std/src/sys/cloudabi/abi/cloudabi.rs
index b02faf1830c..5c4e3fd85c4 100644
--- a/library/std/src/sys/cloudabi/abi/cloudabi.rs
+++ b/library/std/src/sys/cloudabi/abi/cloudabi.rs
@@ -1910,7 +1910,7 @@ extern "C" {
 /// The resolution of the clock.
 #[inline]
 pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
-    cloudabi_sys_clock_res_get(clock_id_, resolution_)
+    unsafe { cloudabi_sys_clock_res_get(clock_id_, resolution_) }
 }
 
 /// Obtains the time value of a clock.
@@ -1934,7 +1934,7 @@ pub unsafe fn clock_time_get(
     precision_: timestamp,
     time_: *mut timestamp,
 ) -> errno {
-    cloudabi_sys_clock_time_get(clock_id_, precision_, time_)
+    unsafe { cloudabi_sys_clock_time_get(clock_id_, precision_, time_) }
 }
 
 /// Wakes up threads waiting on a userspace condition variable.
@@ -1961,7 +1961,7 @@ pub unsafe fn clock_time_get(
 /// threads, all threads are woken up.
 #[inline]
 pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
-    cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_)
+    unsafe { cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_) }
 }
 
 /// Closes a file descriptor.
@@ -1972,7 +1972,7 @@ pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: n
 /// The file descriptor that needs to be closed.
 #[inline]
 pub unsafe fn fd_close(fd_: fd) -> errno {
-    cloudabi_sys_fd_close(fd_)
+    unsafe { cloudabi_sys_fd_close(fd_) }
 }
 
 /// Creates a file descriptor.
@@ -1990,7 +1990,7 @@ pub unsafe fn fd_close(fd_: fd) -> errno {
 /// The file descriptor that has been created.
 #[inline]
 pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
-    cloudabi_sys_fd_create1(type_, fd_)
+    unsafe { cloudabi_sys_fd_create1(type_, fd_) }
 }
 
 /// Creates a pair of file descriptors.
@@ -2013,7 +2013,8 @@ pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
 /// The second file descriptor of the pair.
 #[inline]
 pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
-    cloudabi_sys_fd_create2(type_, fd1_, fd2_)
+    // SAFETY: the caller must uphold the safety contract for `cloudabi_sys_fd_create2`.
+    unsafe { cloudabi_sys_fd_create2(type_, fd1_, fd2_) }
 }
 
 /// Synchronizes the data of a file to disk.
@@ -2025,7 +2026,9 @@ pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno
 /// needs to be synchronized to disk.
 #[inline]
 pub unsafe fn fd_datasync(fd_: fd) -> errno {
-    cloudabi_sys_fd_datasync(fd_)
+    // SAFETY: the caller must guarantee that `fd` is valid
+    // for synchronization.
+    unsafe { cloudabi_sys_fd_datasync(fd_) }
 }
 
 /// Duplicates a file descriptor.
@@ -2040,7 +2043,7 @@ pub unsafe fn fd_datasync(fd_: fd) -> errno {
 /// The new file descriptor.
 #[inline]
 pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
-    cloudabi_sys_fd_dup(from_, fd_)
+    unsafe { cloudabi_sys_fd_dup(from_, fd_) }
 }
 
 /// Reads from a file descriptor, without using and updating the
@@ -2064,7 +2067,7 @@ pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
 /// The number of bytes read.
 #[inline]
 pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
-    cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_)
+    unsafe { cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_) }
 }
 
 /// Writes to a file descriptor, without using and updating the
@@ -2093,7 +2096,7 @@ pub unsafe fn fd_pwrite(
     offset_: filesize,
     nwritten_: &mut usize,
 ) -> errno {
-    cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_)
+    unsafe { cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_) }
 }
 
 /// Reads from a file descriptor.
@@ -2112,7 +2115,7 @@ pub unsafe fn fd_pwrite(
 /// The number of bytes read.
 #[inline]
 pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
-    cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_)
+    unsafe { cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_) }
 }
 
 /// Atomically replaces a file descriptor by a copy of another
@@ -2138,7 +2141,7 @@ pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
 /// overwritten.
 #[inline]
 pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
-    cloudabi_sys_fd_replace(from_, to_)
+    unsafe { cloudabi_sys_fd_replace(from_, to_) }
 }
 
 /// Moves the offset of the file descriptor.
@@ -2166,7 +2169,7 @@ pub unsafe fn fd_seek(
     whence_: whence,
     newoffset_: &mut filesize,
 ) -> errno {
-    cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_)
+    unsafe { cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_) }
 }
 
 /// Gets attributes of a file descriptor.
@@ -2182,7 +2185,7 @@ pub unsafe fn fd_seek(
 /// attributes are stored.
 #[inline]
 pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
-    cloudabi_sys_fd_stat_get(fd_, buf_)
+    unsafe { cloudabi_sys_fd_stat_get(fd_, buf_) }
 }
 
 /// Adjusts attributes of a file descriptor.
@@ -2202,7 +2205,7 @@ pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
 /// be adjusted.
 #[inline]
 pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
-    cloudabi_sys_fd_stat_put(fd_, buf_, flags_)
+    unsafe { cloudabi_sys_fd_stat_put(fd_, buf_, flags_) }
 }
 
 /// Synchronizes the data and metadata of a file to disk.
@@ -2214,7 +2217,7 @@ pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> err
 /// and metadata needs to be synchronized to disk.
 #[inline]
 pub unsafe fn fd_sync(fd_: fd) -> errno {
-    cloudabi_sys_fd_sync(fd_)
+    unsafe { cloudabi_sys_fd_sync(fd_) }
 }
 
 /// Writes to a file descriptor.
@@ -2233,7 +2236,7 @@ pub unsafe fn fd_sync(fd_: fd) -> errno {
 /// The number of bytes written.
 #[inline]
 pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
-    cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_)
+    unsafe { cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_) }
 }
 
 /// Provides file advisory information on a file descriptor.
@@ -2256,7 +2259,7 @@ pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errn
 /// The advice.
 #[inline]
 pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
-    cloudabi_sys_file_advise(fd_, offset_, len_, advice_)
+    unsafe { cloudabi_sys_file_advise(fd_, offset_, len_, advice_) }
 }
 
 /// Forces the allocation of space in a file.
@@ -2275,7 +2278,7 @@ pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: a
 /// The length of the area that is allocated.
 #[inline]
 pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
-    cloudabi_sys_file_allocate(fd_, offset_, len_)
+    unsafe { cloudabi_sys_file_allocate(fd_, offset_, len_) }
 }
 
 /// Creates a file of a specified type.
@@ -2296,7 +2299,7 @@ pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno
 ///     Creates a directory.
 #[inline]
 pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
-    cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)
+    unsafe { cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)}
 }
 
 /// Creates a hard link.
@@ -2320,7 +2323,7 @@ pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
 /// should be created.
 #[inline]
 pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len())
+    unsafe { cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len()) }
 }
 
 /// Opens a file.
@@ -2362,7 +2365,7 @@ pub unsafe fn file_open(
     fds_: *const fdstat,
     fd_: &mut fd,
 ) -> errno {
-    cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_)
+    unsafe { cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_) }
 }
 
 /// Reads directory entries from a directory.
@@ -2402,7 +2405,7 @@ pub unsafe fn file_readdir(
     cookie_: dircookie,
     bufused_: &mut usize,
 ) -> errno {
-    cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_)
+    unsafe { cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_) }
 }
 
 /// Reads the contents of a symbolic link.
@@ -2425,14 +2428,16 @@ pub unsafe fn file_readdir(
 /// The number of bytes placed in the buffer.
 #[inline]
 pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
-    cloudabi_sys_file_readlink(
-        fd_,
-        path_.as_ptr(),
-        path_.len(),
-        buf_.as_mut_ptr(),
-        buf_.len(),
-        bufused_,
-    )
+    unsafe {
+        cloudabi_sys_file_readlink(
+            fd_,
+            path_.as_ptr(),
+            path_.len(),
+            buf_.as_mut_ptr(),
+            buf_.len(),
+            bufused_,
+        )
+    }
 }
 
 /// Renames a file.
@@ -2456,14 +2461,16 @@ pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &m
 /// be renamed.
 #[inline]
 pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    cloudabi_sys_file_rename(
-        fd1_,
-        path1_.as_ptr(),
-        path1_.len(),
-        fd2_,
-        path2_.as_ptr(),
-        path2_.len(),
-    )
+    unsafe {
+        cloudabi_sys_file_rename(
+            fd1_,
+            path1_.as_ptr(),
+            path1_.len(),
+            fd2_,
+            path2_.as_ptr(),
+            path2_.len(),
+        )
+    }
 }
 
 /// Gets attributes of a file by file descriptor.
@@ -2479,7 +2486,7 @@ pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> e
 /// stored.
 #[inline]
 pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
-    cloudabi_sys_file_stat_fget(fd_, buf_)
+    unsafe { cloudabi_sys_file_stat_fget(fd_, buf_) }
 }
 
 /// Adjusts attributes of a file by file descriptor.
@@ -2499,7 +2506,7 @@ pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
 /// be adjusted.
 #[inline]
 pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
-    cloudabi_sys_file_stat_fput(fd_, buf_, flags_)
+    unsafe { cloudabi_sys_file_stat_fput(fd_, buf_, flags_) }
 }
 
 /// Gets attributes of a file by path.
@@ -2520,7 +2527,7 @@ pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) ->
 /// stored.
 #[inline]
 pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
-    cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_)
+    unsafe { cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_) }
 }
 
 /// Adjusts attributes of a file by path.
@@ -2550,7 +2557,7 @@ pub unsafe fn file_stat_put(
     buf_: *const filestat,
     flags_: fsflags,
 ) -> errno {
-    cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_)
+    unsafe { cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_) }
 }
 
 /// Creates a symbolic link.
@@ -2569,7 +2576,7 @@ pub unsafe fn file_stat_put(
 /// link should be created.
 #[inline]
 pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
-    cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len())
+    unsafe { cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len()) }
 }
 
 /// Unlinks a file, or removes a directory.
@@ -2591,7 +2598,7 @@ pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
 ///     Otherwise, unlink a file.
 #[inline]
 pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
-    cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_)
+    unsafe { cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_) }
 }
 
 /// Unlocks a write-locked userspace lock.
@@ -2618,7 +2625,7 @@ pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
 /// shared memory.
 #[inline]
 pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
-    cloudabi_sys_lock_unlock(lock_, scope_)
+    unsafe { cloudabi_sys_lock_unlock(lock_, scope_) }
 }
 
 /// Provides memory advisory information on a region of memory.
@@ -2633,7 +2640,7 @@ pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
 /// The advice.
 #[inline]
 pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
-    cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_)
+    unsafe { cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_) }
 }
 
 /// Creates a memory mapping, making the contents of a file
@@ -2682,7 +2689,7 @@ pub unsafe fn mem_map(
     off_: filesize,
     mem_: &mut *mut (),
 ) -> errno {
-    cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_)
+    unsafe { cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_) }
 }
 
 /// Changes the protection of a memory mapping.
@@ -2696,7 +2703,7 @@ pub unsafe fn mem_map(
 /// New protection options.
 #[inline]
 pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
-    cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_)
+    unsafe { cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_) }
 }
 
 /// Synchronizes a region of memory with its physical storage.
@@ -2710,7 +2717,7 @@ pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
 /// The method of synchronization.
 #[inline]
 pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
-    cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_)
+    unsafe { cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_) }
 }
 
 /// Unmaps a region of memory.
@@ -2721,7 +2728,7 @@ pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
 /// The pages that needs to be unmapped.
 #[inline]
 pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
-    cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len())
+    unsafe { cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len()) }
 }
 
 /// Concurrently polls for the occurrence of a set of events.
@@ -2746,7 +2753,7 @@ pub unsafe fn poll(
     nsubscriptions_: usize,
     nevents_: *mut usize,
 ) -> errno {
-    cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_)
+    unsafe { cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_) }
 }
 
 /// Replaces the process by a new executable.
@@ -2784,7 +2791,7 @@ pub unsafe fn poll(
 /// execution.
 #[inline]
 pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
-    cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len())
+    unsafe { cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len()) }
 }
 
 /// Terminates the process normally.
@@ -2797,7 +2804,7 @@ pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
 /// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
 #[inline]
 pub unsafe fn proc_exit(rval_: exitcode) -> ! {
-    cloudabi_sys_proc_exit(rval_)
+    unsafe { cloudabi_sys_proc_exit(rval_) }
 }
 
 /// Forks the process of the calling thread.
@@ -2822,7 +2829,7 @@ pub unsafe fn proc_exit(rval_: exitcode) -> ! {
 /// initial thread of the child process.
 #[inline]
 pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
-    cloudabi_sys_proc_fork(fd_, tid_)
+    unsafe { cloudabi_sys_proc_fork(fd_, tid_) }
 }
 
 /// Sends a signal to the process of the calling thread.
@@ -2837,7 +2844,7 @@ pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
 /// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
 #[inline]
 pub unsafe fn proc_raise(sig_: signal) -> errno {
-    cloudabi_sys_proc_raise(sig_)
+    unsafe { cloudabi_sys_proc_raise(sig_) }
 }
 
 /// Obtains random data from the kernel random number generator.
@@ -2853,7 +2860,7 @@ pub unsafe fn proc_raise(sig_: signal) -> errno {
 /// data.
 #[inline]
 pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
-    cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len())
+    unsafe { cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len()) }
 }
 
 /// Receives a message on a socket.
@@ -2871,7 +2878,7 @@ pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
 /// Output parameters.
 #[inline]
 pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
-    cloudabi_sys_sock_recv(sock_, in_, out_)
+    unsafe { cloudabi_sys_sock_recv(sock_, in_, out_) }
 }
 
 /// Sends a message on a socket.
@@ -2888,7 +2895,7 @@ pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) ->
 /// Output parameters.
 #[inline]
 pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
-    cloudabi_sys_sock_send(sock_, in_, out_)
+    unsafe { cloudabi_sys_sock_send(sock_, in_, out_) }
 }
 
 /// Shuts down socket send and receive channels.
@@ -2903,7 +2910,7 @@ pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) ->
 /// down.
 #[inline]
 pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
-    cloudabi_sys_sock_shutdown(sock_, how_)
+    unsafe { cloudabi_sys_sock_shutdown(sock_, how_) }
 }
 
 /// Creates a new thread within the current process.
@@ -2917,7 +2924,7 @@ pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
 /// The thread ID of the new thread.
 #[inline]
 pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
-    cloudabi_sys_thread_create(attr_, tid_)
+    unsafe { cloudabi_sys_thread_create(attr_, tid_) }
 }
 
 /// Terminates the calling thread.
@@ -2937,11 +2944,11 @@ pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
 /// shared memory.
 #[inline]
 pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
-    cloudabi_sys_thread_exit(lock_, scope_)
+    unsafe { cloudabi_sys_thread_exit(lock_, scope_) }
 }
 
 /// Temporarily yields execution of the calling thread.
 #[inline]
 pub unsafe fn thread_yield() -> errno {
-    cloudabi_sys_thread_yield()
+    unsafe { cloudabi_sys_thread_yield() }
 }
diff --git a/library/std/src/sys/cloudabi/mod.rs b/library/std/src/sys/cloudabi/mod.rs
index f7dd2c8d00f..13f1bc8826e 100644
--- a/library/std/src/sys/cloudabi/mod.rs
+++ b/library/std/src/sys/cloudabi/mod.rs
@@ -1,3 +1,5 @@
+#![deny(unsafe_op_in_unsafe_fn)]
+
 use crate::io::ErrorKind;
 use crate::mem;
 
diff --git a/library/std/src/sys/cloudabi/mutex.rs b/library/std/src/sys/cloudabi/mutex.rs
index 1203d8de0c5..9dafcbc1fba 100644
--- a/library/std/src/sys/cloudabi/mutex.rs
+++ b/library/std/src/sys/cloudabi/mutex.rs
@@ -103,7 +103,9 @@ impl ReentrantMutex {
             };
             let mut event = MaybeUninit::<abi::event>::uninit();
             let mut nevents = MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
+            // SAFE: The caller must to ensure that `event` and `nevents` are initialized.
+            let ret =
+                unsafe { abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()) };
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
             let event = event.assume_init();
             assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 82ccab1462b..829d4c943f1 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -334,10 +334,6 @@ impl File {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         Err(Error::from_raw_os_error(22))
     }
-
-    pub fn diverge(&self) -> ! {
-        loop {}
-    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 8eaf07e52d6..af05310a8d3 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -31,6 +31,7 @@ pub mod net;
 pub mod os;
 pub mod path;
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
 pub mod stack_overflow;
diff --git a/library/std/src/sys/hermit/mutex.rs b/library/std/src/sys/hermit/mutex.rs
index 3d4813209cb..f988a019cfe 100644
--- a/library/std/src/sys/hermit/mutex.rs
+++ b/library/std/src/sys/hermit/mutex.rs
@@ -1,44 +1,214 @@
+use crate::cell::UnsafeCell;
+use crate::collections::VecDeque;
 use crate::ffi::c_void;
+use crate::ops::{Deref, DerefMut, Drop};
 use crate::ptr;
+use crate::sync::atomic::{spin_loop_hint, AtomicUsize, Ordering};
 use crate::sys::hermit::abi;
 
+/// This type provides a lock based on busy waiting to realize mutual exclusion
+///
+/// # Description
+///
+/// This structure behaves a lot like a common mutex. There are some differences:
+///
+/// - By using busy waiting, it can be used outside the runtime.
+/// - It is a so called ticket lock and is completly fair.
+#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
+#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
+struct Spinlock<T: ?Sized> {
+    queue: AtomicUsize,
+    dequeue: AtomicUsize,
+    data: UnsafeCell<T>,
+}
+
+unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
+unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}
+
+/// A guard to which the protected data can be accessed
+///
+/// When the guard falls out of scope it will release the lock.
+struct SpinlockGuard<'a, T: ?Sized + 'a> {
+    dequeue: &'a AtomicUsize,
+    data: &'a mut T,
+}
+
+impl<T> Spinlock<T> {
+    pub const fn new(user_data: T) -> Spinlock<T> {
+        Spinlock {
+            queue: AtomicUsize::new(0),
+            dequeue: AtomicUsize::new(1),
+            data: UnsafeCell::new(user_data),
+        }
+    }
+
+    #[inline]
+    fn obtain_lock(&self) {
+        let ticket = self.queue.fetch_add(1, Ordering::SeqCst) + 1;
+        while self.dequeue.load(Ordering::SeqCst) != ticket {
+            spin_loop_hint();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn lock(&self) -> SpinlockGuard<'_, T> {
+        self.obtain_lock();
+        SpinlockGuard { dequeue: &self.dequeue, data: &mut *self.data.get() }
+    }
+}
+
+impl<T: ?Sized + Default> Default for Spinlock<T> {
+    fn default() -> Spinlock<T> {
+        Spinlock::new(Default::default())
+    }
+}
+
+impl<'a, T: ?Sized> Deref for SpinlockGuard<'a, T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &*self.data
+    }
+}
+
+impl<'a, T: ?Sized> DerefMut for SpinlockGuard<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut *self.data
+    }
+}
+
+impl<'a, T: ?Sized> Drop for SpinlockGuard<'a, T> {
+    /// The dropping of the SpinlockGuard will release the lock it was created from.
+    fn drop(&mut self) {
+        self.dequeue.fetch_add(1, Ordering::SeqCst);
+    }
+}
+
+/// Realize a priority queue for tasks
+struct PriorityQueue {
+    queues: [Option<VecDeque<abi::Tid>>; abi::NO_PRIORITIES],
+    prio_bitmap: u64,
+}
+
+impl PriorityQueue {
+    pub const fn new() -> PriorityQueue {
+        PriorityQueue {
+            queues: [
+                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                None, None, None,
+            ],
+            prio_bitmap: 0,
+        }
+    }
+
+    /// Add a task id by its priority to the queue
+    pub fn push(&mut self, prio: abi::Priority, id: abi::Tid) {
+        let i: usize = prio.into().into();
+        self.prio_bitmap |= (1 << i) as u64;
+        if let Some(queue) = &mut self.queues[i] {
+            queue.push_back(id);
+        } else {
+            let mut queue = VecDeque::new();
+            queue.push_back(id);
+            self.queues[i] = Some(queue);
+        }
+    }
+
+    fn pop_from_queue(&mut self, queue_index: usize) -> Option<abi::Tid> {
+        if let Some(queue) = &mut self.queues[queue_index] {
+            let id = queue.pop_front();
+
+            if queue.is_empty() {
+                self.prio_bitmap &= !(1 << queue_index as u64);
+            }
+
+            id
+        } else {
+            None
+        }
+    }
+
+    /// Pop the task handle with the highest priority from the queue
+    pub fn pop(&mut self) -> Option<abi::Tid> {
+        for i in 0..abi::NO_PRIORITIES {
+            if self.prio_bitmap & (1 << i) != 0 {
+                return self.pop_from_queue(i);
+            }
+        }
+
+        None
+    }
+}
+
+struct MutexInner {
+    locked: bool,
+    blocked_task: PriorityQueue,
+}
+
+impl MutexInner {
+    pub const fn new() -> MutexInner {
+        MutexInner { locked: false, blocked_task: PriorityQueue::new() }
+    }
+}
+
 pub struct Mutex {
-    inner: *const c_void,
+    inner: Spinlock<MutexInner>,
 }
 
+pub type MovableMutex = Box<Mutex>;
+
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 impl Mutex {
     pub const fn new() -> Mutex {
-        Mutex { inner: ptr::null() }
+        Mutex { inner: Spinlock::new(MutexInner::new()) }
     }
 
     #[inline]
     pub unsafe fn init(&mut self) {
-        let _ = abi::sem_init(&mut self.inner as *mut *const c_void, 1);
+        self.inner = Spinlock::new(MutexInner::new());
     }
 
     #[inline]
     pub unsafe fn lock(&self) {
-        let _ = abi::sem_timedwait(self.inner, 0);
+        loop {
+            let mut guard = self.inner.lock();
+            if guard.locked == false {
+                guard.locked = true;
+                return;
+            } else {
+                let prio = abi::get_priority();
+                let id = abi::getpid();
+
+                guard.blocked_task.push(prio, id);
+                abi::block_current_task();
+                drop(guard);
+                abi::yield_now();
+            }
+        }
     }
 
     #[inline]
     pub unsafe fn unlock(&self) {
-        let _ = abi::sem_post(self.inner);
+        let mut guard = self.inner.lock();
+        guard.locked = false;
+        if let Some(tid) = guard.blocked_task.pop() {
+            abi::wakeup_task(tid);
+        }
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        let result = abi::sem_trywait(self.inner);
-        result == 0
+        let mut guard = self.inner.lock();
+        if guard.locked == false {
+            guard.locked = true;
+        }
+        guard.locked
     }
 
     #[inline]
-    pub unsafe fn destroy(&self) {
-        let _ = abi::sem_destroy(self.inner);
-    }
+    pub unsafe fn destroy(&self) {}
 }
 
 pub struct ReentrantMutex {
diff --git a/library/std/src/sys/hermit/process.rs b/library/std/src/sys/hermit/process.rs
deleted file mode 100644
index 4702e5c5492..00000000000
--- a/library/std/src/sys/hermit/process.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 7b5fac922d0..b4628b64911 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -89,6 +89,7 @@ cfg_if::cfg_if! {
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as windows_ext;
     } else if #[cfg(any(target_os = "cloudabi",
+                        target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
         // On CloudABI and wasm right now the shim below doesn't compile, so
diff --git a/library/std/src/sys/sgx/env.rs b/library/std/src/sys/sgx/env.rs
index 6fa0ed7bcf4..8043b7c5213 100644
--- a/library/std/src/sys/sgx/env.rs
+++ b/library/std/src/sys/sgx/env.rs
@@ -1,9 +1,9 @@
 pub mod os {
-    pub const FAMILY: &'static str = "";
-    pub const OS: &'static str = "";
-    pub const DLL_PREFIX: &'static str = "";
-    pub const DLL_SUFFIX: &'static str = ".sgxs";
-    pub const DLL_EXTENSION: &'static str = "sgxs";
-    pub const EXE_SUFFIX: &'static str = ".sgxs";
-    pub const EXE_EXTENSION: &'static str = "sgxs";
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = ".sgxs";
+    pub const DLL_EXTENSION: &str = "sgxs";
+    pub const EXE_SUFFIX: &str = ".sgxs";
+    pub const EXE_EXTENSION: &str = "sgxs";
 }
diff --git a/library/std/src/sys/sgx/path.rs b/library/std/src/sys/sgx/path.rs
index 06c9df3ff54..840a7ae0426 100644
--- a/library/std/src/sys/sgx/path.rs
+++ b/library/std/src/sys/sgx/path.rs
@@ -15,5 +15,5 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
     None
 }
 
-pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP_STR: &str = "/";
 pub const MAIN_SEP: char = '/';
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 776f4f18ecf..b28c6d85b7c 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -220,6 +220,10 @@ where
     }
 }
 
+pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
+    if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
+}
+
 // On Unix-like platforms, libc::abort will unregister signal handlers
 // including the SIGABRT handler, preventing the abort from being blocked, and
 // fclose streams, with the side effect of flushing them so libc buffered
diff --git a/library/std/src/sys/unix/mutex.rs b/library/std/src/sys/unix/mutex.rs
index ebc737b75ae..89c55eb859d 100644
--- a/library/std/src/sys/unix/mutex.rs
+++ b/library/std/src/sys/unix/mutex.rs
@@ -1,5 +1,6 @@
 use crate::cell::UnsafeCell;
 use crate::mem::MaybeUninit;
+use crate::sys::cvt_nz;
 
 pub struct Mutex {
     inner: UnsafeCell<libc::pthread_mutex_t>,
@@ -51,14 +52,11 @@ impl Mutex {
         // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
         // re-lock it from the same thread, thus avoiding undefined behavior.
         let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
-        let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
-        debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
-        debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
-        debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
-        debug_assert_eq!(r, 0);
+        cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
+        let attr = PthreadMutexAttr(&mut attr);
+        cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL))
+            .unwrap();
+        cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
     }
     #[inline]
     pub unsafe fn lock(&self) {
@@ -106,15 +104,11 @@ impl ReentrantMutex {
 
     pub unsafe fn init(&self) {
         let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
-        let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
-        debug_assert_eq!(result, 0);
-        let result =
-            libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE);
-        debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
-        debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
-        debug_assert_eq!(result, 0);
+        cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
+        let attr = PthreadMutexAttr(&mut attr);
+        cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE))
+            .unwrap();
+        cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
     }
 
     pub unsafe fn lock(&self) {
@@ -137,3 +131,14 @@ impl ReentrantMutex {
         debug_assert_eq!(result, 0);
     }
 }
+
+struct PthreadMutexAttr<'a>(&'a mut MaybeUninit<libc::pthread_mutexattr_t>);
+
+impl Drop for PthreadMutexAttr<'_> {
+    fn drop(&mut self) {
+        unsafe {
+            let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr());
+            debug_assert_eq!(result, 0);
+        }
+    }
+}
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index b05319c89e8..a590c744356 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -281,7 +281,7 @@ impl Command {
         envp: Option<&CStringArray>,
     ) -> io::Result<Option<Process>> {
         use crate::mem::MaybeUninit;
-        use crate::sys;
+        use crate::sys::{self, cvt_nz};
 
         if self.get_gid().is_some()
             || self.get_uid().is_some()
@@ -343,10 +343,6 @@ impl Command {
             }
         }
 
-        fn cvt_nz(error: libc::c_int) -> io::Result<()> {
-            if error == 0 { Ok(()) } else { Err(io::Error::from_raw_os_error(error)) }
-        }
-
         unsafe {
             let mut attrs = MaybeUninit::uninit();
             cvt_nz(libc::posix_spawnattr_init(attrs.as_mut_ptr()))?;
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index fdf114d6df6..f1ab302d30e 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -178,7 +178,8 @@ impl Thread {
                     tv_nsec: nsecs,
                 };
                 secs -= ts.tv_sec as u64;
-                if libc::nanosleep(&ts, &mut ts) == -1 {
+                let ts_ptr = &mut ts as *mut _;
+                if libc::nanosleep(ts_ptr, ts_ptr) == -1 {
                     assert_eq!(os::errno(), libc::EINTR);
                     secs += ts.tv_sec as u64;
                     nsecs = ts.tv_nsec;
diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs
index 32b8b5bdaea..b61a7872265 100644
--- a/library/std/src/sys/wasm/alloc.rs
+++ b/library/std/src/sys/wasm/alloc.rs
@@ -24,26 +24,34 @@ static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
 unsafe impl GlobalAlloc for System {
     #[inline]
     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
+        // Calling malloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        DLMALLOC.malloc(layout.size(), layout.align())
+        unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
     }
 
     #[inline]
     unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
+        // Calling calloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        DLMALLOC.calloc(layout.size(), layout.align())
+        unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
     }
 
     #[inline]
     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
+        // Calling free() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        DLMALLOC.free(ptr, layout.size(), layout.align())
+        unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
     }
 
     #[inline]
     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
+        // Calling realloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
+        unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
     }
 }
 
diff --git a/library/std/src/sys/wasm/condvar_atomics.rs b/library/std/src/sys/wasm/condvar_atomics.rs
index a96bb18e6ef..0c1c076cc91 100644
--- a/library/std/src/sys/wasm/condvar_atomics.rs
+++ b/library/std/src/sys/wasm/condvar_atomics.rs
@@ -44,13 +44,19 @@ impl Condvar {
 
     pub unsafe fn notify_one(&self) {
         self.cnt.fetch_add(1, SeqCst);
-        wasm32::memory_atomic_notify(self.ptr(), 1);
+        // SAFETY: ptr() is always valid
+        unsafe {
+            wasm32::memory_atomic_notify(self.ptr(), 1);
+        }
     }
 
     #[inline]
     pub unsafe fn notify_all(&self) {
         self.cnt.fetch_add(1, SeqCst);
-        wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
+        // SAFETY: ptr() is always valid
+        unsafe {
+            wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
+        }
     }
 
     pub unsafe fn wait(&self, mutex: &Mutex) {
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 11c6896f050..82683c0f624 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -14,6 +14,8 @@
 //! compiling for wasm. That way it's a compile time error for something that's
 //! guaranteed to be a runtime error!
 
+#![deny(unsafe_op_in_unsafe_fn)]
+
 pub mod alloc;
 pub mod args;
 #[path = "../unsupported/cmath.rs"]
diff --git a/library/std/src/sys/wasm/mutex_atomics.rs b/library/std/src/sys/wasm/mutex_atomics.rs
index 2970fcf806c..479182ffa44 100644
--- a/library/std/src/sys/wasm/mutex_atomics.rs
+++ b/library/std/src/sys/wasm/mutex_atomics.rs
@@ -28,11 +28,14 @@ impl Mutex {
 
     pub unsafe fn lock(&self) {
         while !self.try_lock() {
-            let val = wasm32::memory_atomic_wait32(
-                self.ptr(),
-                1,  // we expect our mutex is locked
-                -1, // wait infinitely
-            );
+            // SAFETY: the caller must uphold the safety contract for `memory_atomic_wait32`.
+            let val = unsafe {
+                wasm32::memory_atomic_wait32(
+                    self.ptr(),
+                    1,  // we expect our mutex is locked
+                    -1, // wait infinitely
+                )
+            };
             // we should have either woke up (0) or got a not-equal due to a
             // race (1). We should never time out (2)
             debug_assert!(val == 0 || val == 1);
@@ -93,19 +96,20 @@ impl ReentrantMutex {
     pub unsafe fn lock(&self) {
         let me = thread::my_id();
         while let Err(owner) = self._try_lock(me) {
-            let val = wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1);
+            // SAFETY: the caller must gurantee that `self.ptr()` and `owner` are valid i32.
+            let val = unsafe { wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1) };
             debug_assert!(val == 0 || val == 1);
         }
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        self._try_lock(thread::my_id()).is_ok()
+        unsafe { self._try_lock(thread::my_id()).is_ok() }
     }
 
     #[inline]
     unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
-        let id = id.checked_add(1).unwrap(); // make sure `id` isn't 0
+        let id = id.checked_add(1).unwrap();
         match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
             // we transitioned from unlocked to locked
             Ok(_) => {
@@ -132,7 +136,10 @@ impl ReentrantMutex {
         match *self.recursions.get() {
             0 => {
                 self.owner.swap(0, SeqCst);
-                wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1); // wake up one waiter, if any
+                // SAFETY: the caller must gurantee that `self.ptr()` is valid i32.
+                unsafe {
+                    wasm32::atomic_notify(self.ptr() as *mut i32, 1);
+                } // wake up one waiter, if any
             }
             ref mut n => *n -= 1,
         }
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 45c10266ba2..bdb8fc7807b 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -457,11 +457,16 @@ impl Builder {
         let my_packet: Arc<UnsafeCell<Option<Result<T>>>> = Arc::new(UnsafeCell::new(None));
         let their_packet = my_packet.clone();
 
+        let (stdout, stderr) = crate::io::clone_io();
+
         let main = move || {
             if let Some(name) = their_thread.cname() {
                 imp::Thread::set_name(name);
             }
 
+            crate::io::set_print(stdout);
+            crate::io::set_panic(stderr);
+
             // SAFETY: the stack guard passed is the one for the current thread.
             // This means the current thread's stack and the new thread's stack
             // are properly set and protected from each other.