diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index b6b349e4a803d..b683626bbd64d 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -75,19 +75,21 @@ impl_stable_hash_via_hash!(OptLevel);
 
 /// This is what the `LtoCli` values get mapped to after resolving defaults and
 /// and taking other command line options into account.
+///
+/// Note that linker plugin-based LTO is a different mechanism entirely.
 #[derive(Clone, PartialEq)]
 pub enum Lto {
-    /// Don't do any LTO whatsoever
+    /// Don't do any LTO whatsoever.
     No,
 
-    /// Do a full crate graph LTO with ThinLTO
+    /// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
     Thin,
 
-    /// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
-    /// units).
+    /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
+    /// only relevant if multiple CGUs are used.
     ThinLocal,
 
-    /// Do a full crate graph LTO with "fat" LTO
+    /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
     Fat,
 }
 
diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs
index bddaab0c76188..b4741c35c583f 100644
--- a/library/alloc/src/tests.rs
+++ b/library/alloc/src/tests.rs
@@ -49,17 +49,17 @@ fn test_show() {
     let b = Box::new(Test) as Box<dyn Any>;
     let a_str = format!("{:?}", a);
     let b_str = format!("{:?}", b);
-    assert_eq!(a_str, "Any");
-    assert_eq!(b_str, "Any");
+    assert_eq!(a_str, "Any { .. }");
+    assert_eq!(b_str, "Any { .. }");
 
     static EIGHT: usize = 8;
     static TEST: Test = Test;
     let a = &EIGHT as &dyn Any;
     let b = &TEST as &dyn Any;
     let s = format!("{:?}", a);
-    assert_eq!(s, "Any");
+    assert_eq!(s, "Any { .. }");
     let s = format!("{:?}", b);
-    assert_eq!(s, "Any");
+    assert_eq!(s, "Any { .. }");
 }
 
 #[test]
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 98c34f344251e..5e1725cfc7a63 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -141,7 +141,7 @@ impl<T: 'static + ?Sized> Any for T {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for dyn Any {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Any")
+        f.debug_struct("Any").finish_non_exhaustive()
     }
 }
 
@@ -151,14 +151,14 @@ impl fmt::Debug for dyn Any {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for dyn Any + Send {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Any")
+        f.debug_struct("Any").finish_non_exhaustive()
     }
 }
 
 #[stable(feature = "any_send_sync_methods", since = "1.28.0")]
 impl fmt::Debug for dyn Any + Send + Sync {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Any")
+        f.debug_struct("Any").finish_non_exhaustive()
     }
 }
 
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index a8a25f927163c..4780d8dc7883f 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -145,6 +145,6 @@ impl fmt::Display for EscapeDefault {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for EscapeDefault {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("EscapeDefault { .. }")
+        f.debug_struct("EscapeDefault").finish_non_exhaustive()
     }
 }
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index 9302baa823bc5..b208ddd4b272f 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -53,7 +53,7 @@ pub enum c_void {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for c_void {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("c_void")
+        f.debug_struct("c_void").finish()
     }
 }
 
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 475ebcf07d5ed..b660788c0515f 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -188,28 +188,19 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     #[stable(feature = "debug_non_exhaustive", since = "1.53.0")]
     pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
         self.result = self.result.and_then(|_| {
-            // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
-            if self.is_pretty() {
-                if !self.has_fields {
-                    self.fmt.write_str(" {\n")?;
-                }
-                let mut slot = None;
-                let mut state = Default::default();
-                let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
-                writer.write_str("..\n")?;
-            } else {
-                if self.has_fields {
-                    self.fmt.write_str(", ..")?;
+            if self.has_fields {
+                if self.is_pretty() {
+                    let mut slot = None;
+                    let mut state = Default::default();
+                    let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
+                    writer.write_str("..\n")?;
+                    self.fmt.write_str("}")
                 } else {
-                    self.fmt.write_str(" { ..")?;
+                    self.fmt.write_str(", .. }")
                 }
-            }
-            if self.is_pretty() {
-                self.fmt.write_str("}")?
             } else {
-                self.fmt.write_str(" }")?;
+                self.fmt.write_str(" { .. }")
             }
-            Ok(())
         });
         self.result
     }
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 59493bb0425f3..87042d95fbef0 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -2220,7 +2220,7 @@ impl Debug for () {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Debug for PhantomData<T> {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        f.pad("PhantomData")
+        f.debug_struct("PhantomData").finish()
     }
 }
 
@@ -2270,7 +2270,7 @@ impl<T: ?Sized + Debug> Debug for RefMut<'_, T> {
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T: ?Sized> Debug for UnsafeCell<T> {
     fn fmt(&self, f: &mut Formatter<'_>) -> Result {
-        f.pad("UnsafeCell")
+        f.debug_struct("UnsafeCell").finish_non_exhaustive()
     }
 }
 
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 0c3303cc21094..7dbd68b73f05a 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -507,7 +507,7 @@ pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
 #[stable(since = "1.9.0", feature = "core_impl_debug")]
 impl<H> fmt::Debug for BuildHasherDefault<H> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("BuildHasherDefault")
+        f.debug_struct("BuildHasherDefault").finish()
     }
 }
 
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 5d4a9fe8c6cc0..919c564f2872a 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -36,7 +36,7 @@ unsafe impl<T> Sync for Empty<T> {}
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T> fmt::Debug for Empty<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Empty")
+        f.debug_struct("Empty").finish()
     }
 }
 
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 81262a2f91839..6b9b435d47fe9 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -23,7 +23,7 @@ macro_rules! impl_nonzero_fmt {
 }
 
 macro_rules! nonzero_integers {
-    ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
+    ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => {
         $(
             /// An integer that is known not to equal zero.
             ///
@@ -48,7 +48,7 @@ macro_rules! nonzero_integers {
                 ///
                 /// The value must not be zero.
                 #[$stability]
-                #[rustc_const_stable(feature = "nonzero", since = "1.34.0")]
+                #[$const_new_unchecked_stability]
                 #[inline]
                 pub const unsafe fn new_unchecked(n: $Int) -> Self {
                     // SAFETY: this is guaranteed to be safe by the caller.
@@ -146,18 +146,18 @@ macro_rules! nonzero_integers {
 }
 
 nonzero_integers! {
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
-    #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
-    #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
+    #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
+    #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
 }
 
 macro_rules! from_str_radix_nzint_impl {
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index a8dea4e9b4ea8..964378cc9c3c6 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -61,6 +61,10 @@ pub trait Index<Idx: ?Sized> {
     type Output: ?Sized;
 
     /// Performs the indexing (`container[index]`) operation.
+    ///
+    /// # Panics
+    ///
+    /// May panic if the index is out of bounds.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[track_caller]
     fn index(&self, index: Idx) -> &Self::Output;
@@ -161,6 +165,10 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
 #[doc(alias = "[]")]
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
     /// Performs the mutable indexing (`container[index]`) operation.
+    ///
+    /// # Panics
+    ///
+    /// May panic if the index is out of bounds.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[track_caller]
     fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 22fa08b979570..906dcb1e8bcee 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -146,7 +146,7 @@ impl<'a> fmt::Display for EscapeAscii<'a> {
 #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
 impl<'a> fmt::Debug for EscapeAscii<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("EscapeAscii { .. }")
+        f.debug_struct("EscapeAscii").finish_non_exhaustive()
     }
 }
 
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 4eac017f9153c..7ebff180f9d73 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1359,7 +1359,7 @@ pub struct EncodeUtf16<'a> {
 #[stable(feature = "collection_debug", since = "1.17.0")]
 impl fmt::Debug for EncodeUtf16<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("EncodeUtf16 { .. }")
+        f.debug_struct("EncodeUtf16").finish_non_exhaustive()
     }
 }
 
diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs
index 129c121e8ceac..7580010a28b4a 100644
--- a/library/core/tests/fmt/builders.rs
+++ b/library/core/tests/fmt/builders.rs
@@ -105,12 +105,7 @@ mod debug_struct {
         }
 
         assert_eq!("Foo { .. }", format!("{:?}", Foo));
-        assert_eq!(
-            "Foo {
-    ..
-}",
-            format!("{:#?}", Foo)
-        );
+        assert_eq!("Foo { .. }", format!("{:#?}", Foo));
     }
 
     #[test]
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 3dcc5cd2b5911..bdf559847cc85 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2257,7 +2257,7 @@ where
     F: FnMut(&K, &mut V) -> bool,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("DrainFilter { .. }")
+        f.debug_struct("DrainFilter").finish_non_exhaustive()
     }
 }
 
@@ -2957,7 +2957,7 @@ impl Default for RandomState {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for RandomState {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("RandomState { .. }")
+        f.debug_struct("RandomState").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 8c801b9f1285d..5220c8ad70977 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -1533,7 +1533,7 @@ where
     F: FnMut(&K) -> bool,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("DrainFilter { .. }")
+        f.debug_struct("DrainFilter").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 9763a2da34151..8f8d4e3a89832 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -154,7 +154,7 @@ impl Iterator for Vars {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Vars {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Vars { .. }")
+        f.debug_struct("Vars").finish_non_exhaustive()
     }
 }
 
@@ -172,7 +172,7 @@ impl Iterator for VarsOs {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for VarsOs {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("VarsOs { .. }")
+        f.debug_struct("VarOs").finish_non_exhaustive()
     }
 }
 
@@ -419,7 +419,7 @@ impl<'a> Iterator for SplitPaths<'a> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for SplitPaths<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("SplitPaths { .. }")
+        f.debug_struct("SplitPaths").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 1e72c9e0611ea..c2e0b24ba8327 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -373,7 +373,7 @@ impl Stdin {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdin {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Stdin { .. }")
+        f.debug_struct("Stdin").finish_non_exhaustive()
     }
 }
 
@@ -467,7 +467,7 @@ impl BufRead for StdinLock<'_> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StdinLock<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("StdinLock { .. }")
+        f.debug_struct("StdinLock").finish_non_exhaustive()
     }
 }
 
@@ -607,7 +607,7 @@ impl Stdout {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdout {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Stdout { .. }")
+        f.debug_struct("Stdout").finish_non_exhaustive()
     }
 }
 
@@ -689,7 +689,7 @@ impl Write for StdoutLock<'_> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StdoutLock<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("StdoutLock { .. }")
+        f.debug_struct("StdoutLock").finish_non_exhaustive()
     }
 }
 
@@ -804,7 +804,7 @@ impl Stderr {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stderr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Stderr { .. }")
+        f.debug_struct("Stderr").finish_non_exhaustive()
     }
 }
 
@@ -886,7 +886,7 @@ impl Write for StderrLock<'_> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for StderrLock<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("StderrLock { .. }")
+        f.debug_struct("StderrLock").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs
index f472361f916db..73f2f3eb3f5dc 100644
--- a/library/std/src/io/util.rs
+++ b/library/std/src/io/util.rs
@@ -78,7 +78,7 @@ impl Seek for Empty {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Empty {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Empty { .. }")
+        f.debug_struct("Empty").finish_non_exhaustive()
     }
 }
 
@@ -150,7 +150,7 @@ impl Read for Repeat {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Repeat {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Repeat { .. }")
+        f.debug_struct("Repeat").finish_non_exhaustive()
     }
 }
 
@@ -236,6 +236,6 @@ impl Write for &Sink {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Sink {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Sink { .. }")
+        f.debug_struct("Sink").finish_non_exhaustive()
     }
 }
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 5690de681cab9..931b3b600a302 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -312,7 +312,7 @@ impl FromInner<AnonPipe> for ChildStdin {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdin {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("ChildStdin { .. }")
+        f.debug_struct("ChildStdin").finish_non_exhaustive()
     }
 }
 
@@ -373,7 +373,7 @@ impl FromInner<AnonPipe> for ChildStdout {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStdout {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("ChildStdout { .. }")
+        f.debug_struct("ChildStdout").finish_non_exhaustive()
     }
 }
 
@@ -434,7 +434,7 @@ impl FromInner<AnonPipe> for ChildStderr {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for ChildStderr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("ChildStderr { .. }")
+        f.debug_struct("ChildStderr").finish_non_exhaustive()
     }
 }
 
@@ -1257,7 +1257,7 @@ impl FromInner<imp::Stdio> for Stdio {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdio {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Stdio { .. }")
+        f.debug_struct("Stdio").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs
index eab26b6c7150c..a17b82f82e8c2 100644
--- a/library/std/src/sync/barrier.rs
+++ b/library/std/src/sync/barrier.rs
@@ -60,7 +60,7 @@ pub struct BarrierWaitResult(bool);
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Barrier {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Barrier { .. }")
+        f.debug_struct("Barrier").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index ffc1e57f4e03f..60be63c9543fa 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -548,7 +548,7 @@ impl Condvar {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Condvar {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Condvar { .. }")
+        f.debug_struct("Condvar").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index c8f0a6b99fe6b..ea1d598d26461 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -1477,7 +1477,7 @@ impl<T> fmt::Debug for Receiver<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for SendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "SendError(..)".fmt(f)
+        f.debug_struct("SendError").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index a24a5cb2ae39f..6da6c18e47799 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -481,7 +481,7 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Once {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("Once { .. }")
+        f.debug_struct("Once").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 0f33282fa8370..5b3f2fa4e8275 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -9,7 +9,7 @@ use crate::sys::hermit::abi;
 use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
 use crate::sys::hermit::fd::FileDesc;
 use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::sys_common::os_str_bytes::OsStrExt;
 
 pub use crate::sys_common::fs::copy;
@@ -22,11 +22,11 @@ fn cstr(path: &Path) -> io::Result<CString> {
 #[derive(Debug)]
 pub struct File(FileDesc);
 
-pub struct FileAttr(Void);
+pub struct FileAttr(!);
 
-pub struct ReadDir(Void);
+pub struct ReadDir(!);
 
-pub struct DirEntry(Void);
+pub struct DirEntry(!);
 
 #[derive(Clone, Debug)]
 pub struct OpenOptions {
@@ -41,64 +41,64 @@ pub struct OpenOptions {
     mode: i32,
 }
 
-pub struct FilePermissions(Void);
+pub struct FilePermissions(!);
 
-pub struct FileType(Void);
+pub struct FileType(!);
 
 #[derive(Debug)]
 pub struct DirBuilder {}
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
-        match self.0 {}
+        self.0
     }
 
     pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_type(&self) -> FileType {
-        match self.0 {}
+        self.0
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FileAttr {
     fn clone(&self) -> FileAttr {
-        match self.0 {}
+        self.0
     }
 }
 
 impl FilePermissions {
     pub fn readonly(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FilePermissions {
     fn clone(&self) -> FilePermissions {
-        match self.0 {}
+        self.0
     }
 }
 
 impl PartialEq for FilePermissions {
     fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -106,27 +106,27 @@ impl Eq for FilePermissions {}
 
 impl fmt::Debug for FilePermissions {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
 impl FileType {
     pub fn is_dir(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_file(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_symlink(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FileType {
     fn clone(&self) -> FileType {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -134,7 +134,7 @@ impl Copy for FileType {}
 
 impl PartialEq for FileType {
     fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -142,19 +142,19 @@ impl Eq for FileType {}
 
 impl Hash for FileType {
     fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for FileType {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for ReadDir {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -162,25 +162,25 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_name(&self) -> OsString {
-        match self.0 {}
+        self.0
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index f8c1612d1ca03..56497162c0333 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -61,11 +61,6 @@ pub fn unsupported_err() -> crate::io::Error {
     )
 }
 
-// This enum is used as the storage for a bunch of types which can't actually
-// exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
 pub unsafe fn strlen(start: *const c_char) -> usize {
     let mut str = start;
 
diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs
index a9c09b6ceefae..5f8839157eafc 100644
--- a/library/std/src/sys/hermit/net.rs
+++ b/library/std/src/sys/hermit/net.rs
@@ -6,7 +6,7 @@ use crate::str;
 use crate::sync::Arc;
 use crate::sys::hermit::abi;
 use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::sys_common::AsInner;
 use crate::time::Duration;
 
@@ -411,18 +411,18 @@ impl fmt::Debug for UdpSocket {
     }
 }
 
-pub struct LookupHost(Void);
+pub struct LookupHost(!);
 
 impl LookupHost {
     pub fn port(&self) -> u16 {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs
index 78eabf8f81e98..4487e9d636cb0 100644
--- a/library/std/src/sys/hermit/os.rs
+++ b/library/std/src/sys/hermit/os.rs
@@ -9,7 +9,7 @@ use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::sys_common::os_str_bytes::*;
 use crate::vec;
 
@@ -29,7 +29,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> {
     unsupported()
 }
 
-pub struct SplitPaths<'a>(&'a Void);
+pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
 
 pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
@@ -38,7 +38,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
 impl<'a> Iterator for SplitPaths<'a> {
     type Item = PathBuf;
     fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 50c2660ebcf1f..2450a7aac5ede 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -25,10 +25,7 @@
 mod common;
 
 cfg_if::cfg_if! {
-    if #[cfg(target_os = "vxworks")] {
-        mod vxworks;
-        pub use self::vxworks::*;
-    } else if #[cfg(unix)] {
+    if #[cfg(unix)] {
         mod unix;
         pub use self::unix::*;
     } else if #[cfg(windows)] {
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index da37d1aeb7e74..d6a5683073309 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -115,11 +115,6 @@ pub fn decode_error_kind(code: i32) -> ErrorKind {
     }
 }
 
-// This enum is used as the storage for a bunch of types which can't actually
-// exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
 pub unsafe fn strlen(mut s: *const c_char) -> usize {
     let mut n = 0;
     while unsafe { *s } != 0 {
diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs
index c0c5d55548c5f..5ccedece0f84b 100644
--- a/library/std/src/sys/sgx/net.rs
+++ b/library/std/src/sys/sgx/net.rs
@@ -5,7 +5,7 @@ use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
 use crate::sync::Arc;
 use crate::sys::fd::FileDesc;
-use crate::sys::{sgx_ineffective, unsupported, AsInner, FromInner, IntoInner, TryIntoInner, Void};
+use crate::sys::{sgx_ineffective, unsupported, AsInner, FromInner, IntoInner, TryIntoInner};
 use crate::time::Duration;
 
 use super::abi::usercalls;
@@ -310,7 +310,7 @@ impl FromInner<Socket> for TcpListener {
     }
 }
 
-pub struct UdpSocket(Void);
+pub struct UdpSocket(!);
 
 impl UdpSocket {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
@@ -318,129 +318,129 @@ impl UdpSocket {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        self.0
     }
 
     pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        self.0
     }
 
     pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn broadcast(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for UdpSocket {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -462,7 +462,7 @@ impl fmt::Display for NonIpSockAddr {
     }
 }
 
-pub struct LookupHost(Void);
+pub struct LookupHost(!);
 
 impl LookupHost {
     fn new(host: String) -> io::Result<LookupHost> {
@@ -470,14 +470,14 @@ impl LookupHost {
     }
 
     pub fn port(&self) -> u16 {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/sgx/os.rs b/library/std/src/sys/sgx/os.rs
index 56fc84b4a3fca..144248d60c9cf 100644
--- a/library/std/src/sys/sgx/os.rs
+++ b/library/std/src/sys/sgx/os.rs
@@ -5,12 +5,13 @@ use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
+use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::Mutex;
 use crate::sync::Once;
-use crate::sys::{decode_error_kind, sgx_ineffective, unsupported, Void};
+use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
 use crate::vec;
 
 pub fn errno() -> i32 {
@@ -35,7 +36,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> {
     sgx_ineffective(())
 }
 
-pub struct SplitPaths<'a>(&'a Void);
+pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
 
 pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
@@ -44,7 +45,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
 impl<'a> Iterator for SplitPaths<'a> {
     type Item = PathBuf;
     fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 7f5e9b04dba4b..3a88dc083b06c 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -173,3 +173,14 @@ pub mod os {
     pub const EXE_SUFFIX: &str = "";
     pub const EXE_EXTENSION: &str = "";
 }
+
+#[cfg(target_os = "vxworks")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "vxworks";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs
index e5048f7e545e0..735bf35a3ced6 100644
--- a/library/std/src/sys/unix/ext/mod.rs
+++ b/library/std/src/sys/unix/ext/mod.rs
@@ -62,6 +62,8 @@ cfg_if::cfg_if! {
         use crate::os::redox as platform;
         #[cfg(target_os = "solaris")]
         use crate::os::solaris as platform;
+        #[cfg(target_os = "vxworks")]
+        use crate::os::vxworks as platform;
     }
 }
 
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 6e44ac19c7b2c..1316835a89d12 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -71,6 +71,7 @@ pub fn init() {
         } else if #[cfg(not(any(
             target_os = "emscripten",
             target_os = "fuchsia",
+            target_os = "vxworks",
             // The poll on Darwin doesn't set POLLNVAL for closed fds.
             target_os = "macos",
             target_os = "ios",
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 98e578c5255c7..bf649f6d76f81 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -85,11 +85,6 @@ pub fn errno() -> i32 {
     unsafe { libc::errnoGet() }
 }
 
-#[cfg(target_os = "vxworks")]
-pub fn set_errno(e: i32) {
-    unsafe { libc::errnoSet(e as c_int) };
-}
-
 #[cfg(target_os = "dragonfly")]
 pub fn errno() -> i32 {
     extern "C" {
@@ -642,7 +637,7 @@ pub fn getppid() -> u32 {
     unsafe { libc::getppid() as u32 }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
 pub fn glibc_version() -> Option<(usize, usize)> {
     if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
         parse_glibc_version(version_str)
@@ -651,7 +646,7 @@ pub fn glibc_version() -> Option<(usize, usize)> {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
 fn glibc_version_cstr() -> Option<&'static CStr> {
     weak! {
         fn gnu_get_libc_version() -> *const libc::c_char
@@ -665,7 +660,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> {
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split('.').map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs
index 1b7b93f9d4a5f..f67c70c01772f 100644
--- a/library/std/src/sys/unix/process/mod.rs
+++ b/library/std/src/sys/unix/process/mod.rs
@@ -4,11 +4,17 @@ pub use crate::ffi::OsString as EnvKey;
 pub use crate::sys_common::process::CommandEnvs;
 
 mod process_common;
-#[cfg(not(target_os = "fuchsia"))]
-#[path = "process_unix.rs"]
-mod process_inner;
-#[cfg(target_os = "fuchsia")]
-#[path = "process_fuchsia.rs"]
-mod process_inner;
-#[cfg(target_os = "fuchsia")]
-mod zircon;
+
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "fuchsia")] {
+        #[path = "process_fuchsia.rs"]
+        mod process_inner;
+        mod zircon;
+    } else if #[cfg(target_os = "vxworks")] {
+        #[path = "process_vxworks.rs"]
+        mod process_inner;
+    } else {
+        #[path = "process_unix.rs"]
+        mod process_inner;
+    }
+}
diff --git a/library/std/src/sys/vxworks/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
similarity index 91%
rename from library/std/src/sys/vxworks/process/process_vxworks.rs
rename to library/std/src/sys/unix/process/process_vxworks.rs
index 295452327eb70..eecdb624b9cfa 100644
--- a/library/std/src/sys/vxworks/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -18,7 +18,6 @@ impl Command {
         needs_stdin: bool,
     ) -> io::Result<(Process, StdioPipes)> {
         use crate::sys::cvt_r;
-        const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
         let envp = self.capture_env();
 
         if self.saw_nul() {
@@ -61,6 +60,9 @@ impl Command {
                 t!(cvt(libc::chdir(cwd.as_ptr())));
             }
 
+            // pre_exec closures are ignored on VxWorks
+            let _ = self.get_closures();
+
             let c_envp = envp
                 .as_ref()
                 .map(|c| c.as_ptr())
@@ -68,7 +70,7 @@ impl Command {
             let stack_size = thread::min_stack();
 
             // ensure that access to the environment is synchronized
-            let _lock = sys::os::env_lock();
+            let _lock = sys::os::env_read_lock();
 
             let ret = libc::rtpSpawn(
                 self.get_program_cstr().as_ptr(),
@@ -196,6 +198,24 @@ impl ExitStatus {
     pub fn signal(&self) -> Option<i32> {
         if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None }
     }
+
+    pub fn core_dumped(&self) -> bool {
+        // This method is not yet properly implemented on VxWorks
+        false
+    }
+
+    pub fn stopped_signal(&self) -> Option<i32> {
+        if libc::WIFSTOPPED(self.0) { Some(libc::WSTOPSIG(self.0)) } else { None }
+    }
+
+    pub fn continued(&self) -> bool {
+        // This method is not yet properly implemented on VxWorks
+        false
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        self.0
+    }
 }
 
 /// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index 38ddb41700c4b..44f9eabc319a0 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -18,7 +18,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     not(target_os = "freebsd"),
     not(target_os = "netbsd"),
     not(target_os = "fuchsia"),
-    not(target_os = "redox")
+    not(target_os = "redox"),
+    not(target_os = "vxworks")
 ))]
 mod imp {
     use crate::fs::File;
@@ -237,3 +238,29 @@ mod imp {
         file.read_exact(v).expect("failed to read rand:")
     }
 }
+
+#[cfg(target_os = "vxworks")]
+mod imp {
+    use crate::io;
+    use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
+
+    pub fn fill_bytes(v: &mut [u8]) {
+        static RNG_INIT: AtomicBool = AtomicBool::new(false);
+        while !RNG_INIT.load(Relaxed) {
+            let ret = unsafe { libc::randSecure() };
+            if ret < 0 {
+                panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
+            } else if ret > 0 {
+                RNG_INIT.store(true, Relaxed);
+                break;
+            }
+            unsafe { libc::usleep(10) };
+        }
+        let ret = unsafe {
+            libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
+        };
+        if ret < 0 {
+            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
+        }
+    }
+}
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index c3275eb6f0e50..c3f410353b915 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -92,3 +92,9 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
         }
     }
 }
+
+#[cfg(target_os = "vxworks")]
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+    use crate::sys_common::thread_local_dtor::register_dtor_fallback;
+    register_dtor_fallback(t, dtor);
+}
diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs
index 64ec50fa9ec00..0ef84c84ee877 100644
--- a/library/std/src/sys/unsupported/common.rs
+++ b/library/std/src/sys/unsupported/common.rs
@@ -36,11 +36,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     (1, 2)
 }
 
-// This enum is used as the storage for a bunch of types which can't actually
-// exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
 pub unsafe fn strlen(mut s: *const c_char) -> usize {
     // SAFETY: The caller must guarantee `s` points to a valid 0-terminated string.
     unsafe {
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index 4271d9b334588..cd533761e3732 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -4,77 +4,77 @@ use crate::hash::{Hash, Hasher};
 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 
-pub struct File(Void);
+pub struct File(!);
 
-pub struct FileAttr(Void);
+pub struct FileAttr(!);
 
-pub struct ReadDir(Void);
+pub struct ReadDir(!);
 
-pub struct DirEntry(Void);
+pub struct DirEntry(!);
 
 #[derive(Clone, Debug)]
 pub struct OpenOptions {}
 
-pub struct FilePermissions(Void);
+pub struct FilePermissions(!);
 
-pub struct FileType(Void);
+pub struct FileType(!);
 
 #[derive(Debug)]
 pub struct DirBuilder {}
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
-        match self.0 {}
+        self.0
     }
 
     pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_type(&self) -> FileType {
-        match self.0 {}
+        self.0
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FileAttr {
     fn clone(&self) -> FileAttr {
-        match self.0 {}
+        self.0
     }
 }
 
 impl FilePermissions {
     pub fn readonly(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FilePermissions {
     fn clone(&self) -> FilePermissions {
-        match self.0 {}
+        self.0
     }
 }
 
 impl PartialEq for FilePermissions {
     fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -82,27 +82,27 @@ impl Eq for FilePermissions {}
 
 impl fmt::Debug for FilePermissions {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
 impl FileType {
     pub fn is_dir(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_file(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_symlink(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for FileType {
     fn clone(&self) -> FileType {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -110,7 +110,7 @@ impl Copy for FileType {}
 
 impl PartialEq for FileType {
     fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -118,19 +118,19 @@ impl Eq for FileType {}
 
 impl Hash for FileType {
     fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for FileType {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for ReadDir {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -138,25 +138,25 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_name(&self) -> OsString {
-        match self.0 {}
+        self.0
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -179,59 +179,59 @@ impl File {
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn fsync(&self) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn datasync(&self) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn truncate(&self, _size: u64) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn flush(&self) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        match self.0 {}
+        self.0
     }
 
     pub fn duplicate(&self) -> io::Result<File> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -247,7 +247,7 @@ impl DirBuilder {
 
 impl fmt::Debug for File {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unsupported/net.rs b/library/std/src/sys/unsupported/net.rs
index 5c9f1098f9b7f..96203c74b576c 100644
--- a/library/std/src/sys/unsupported/net.rs
+++ b/library/std/src/sys/unsupported/net.rs
@@ -2,10 +2,10 @@ use crate::convert::TryFrom;
 use crate::fmt;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::time::Duration;
 
-pub struct TcpStream(Void);
+pub struct TcpStream(!);
 
 impl TcpStream {
     pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
@@ -17,97 +17,97 @@ impl TcpStream {
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for TcpStream {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
-pub struct TcpListener(Void);
+pub struct TcpListener(!);
 
 impl TcpListener {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
@@ -115,49 +115,49 @@ impl TcpListener {
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        match self.0 {}
+        self.0
     }
 
     pub fn duplicate(&self) -> io::Result<TcpListener> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn only_v6(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for TcpListener {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
-pub struct UdpSocket(Void);
+pub struct UdpSocket(!);
 
 impl UdpSocket {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
@@ -165,144 +165,144 @@ impl UdpSocket {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 
     pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        self.0
     }
 
     pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
+        self.0
     }
 
     pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn broadcast(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        match self.0 {}
+        self.0
     }
 
     pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
+        self.0
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
+        self.0
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Debug for UdpSocket {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
-pub struct LookupHost(Void);
+pub struct LookupHost(!);
 
 impl LookupHost {
     pub fn port(&self) -> u16 {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs
index 3754aebf45581..e30395a0b1d92 100644
--- a/library/std/src/sys/unsupported/os.rs
+++ b/library/std/src/sys/unsupported/os.rs
@@ -1,8 +1,9 @@
-use super::{unsupported, Void};
+use super::unsupported;
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
+use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
 
 pub fn errno() -> i32 {
@@ -21,7 +22,7 @@ pub fn chdir(_: &path::Path) -> io::Result<()> {
     unsupported()
 }
 
-pub struct SplitPaths<'a>(&'a Void);
+pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
 
 pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
@@ -30,7 +31,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
 impl<'a> Iterator for SplitPaths<'a> {
     type Item = PathBuf;
     fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
+        self.0
     }
 }
 
@@ -62,12 +63,12 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub struct Env(Void);
+pub struct Env(!);
 
 impl Iterator for Env {
     type Item = (OsString, OsString);
     fn next(&mut self) -> Option<(OsString, OsString)> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unsupported/pipe.rs b/library/std/src/sys/unsupported/pipe.rs
index 10d0925823eb9..25514c2322fa4 100644
--- a/library/std/src/sys/unsupported/pipe.rs
+++ b/library/std/src/sys/unsupported/pipe.rs
@@ -1,35 +1,34 @@
 use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
 
-pub struct AnonPipe(Void);
+pub struct AnonPipe(!);
 
 impl AnonPipe {
     pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
+        self.0
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn diverge(&self) -> ! {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs
index 3ede2291d5a91..38ac0a1ddd5f9 100644
--- a/library/std/src/sys/unsupported/process.rs
+++ b/library/std/src/sys/unsupported/process.rs
@@ -5,7 +5,7 @@ use crate::marker::PhantomData;
 use crate::path::Path;
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::sys_common::process::{CommandEnv, CommandEnvs};
 
 pub use crate::ffi::OsString as EnvKey;
@@ -94,21 +94,21 @@ impl fmt::Debug for Command {
     }
 }
 
-pub struct ExitStatus(Void);
+pub struct ExitStatus(!);
 
 impl ExitStatus {
     pub fn success(&self) -> bool {
-        match self.0 {}
+        self.0
     }
 
     pub fn code(&self) -> Option<i32> {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Clone for ExitStatus {
     fn clone(&self) -> ExitStatus {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -116,7 +116,7 @@ impl Copy for ExitStatus {}
 
 impl PartialEq for ExitStatus {
     fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -124,13 +124,13 @@ impl Eq for ExitStatus {}
 
 impl fmt::Debug for ExitStatus {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
 impl fmt::Display for ExitStatus {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
+        self.0
     }
 }
 
@@ -146,23 +146,23 @@ impl ExitCode {
     }
 }
 
-pub struct Process(Void);
+pub struct Process(!);
 
 impl Process {
     pub fn id(&self) -> u32 {
-        match self.0 {}
+        self.0
     }
 
     pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
+        self.0
     }
 
     pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
+        self.0
     }
 
     pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/unsupported/thread.rs b/library/std/src/sys/unsupported/thread.rs
index 20ae309db30d7..cda8510e1baeb 100644
--- a/library/std/src/sys/unsupported/thread.rs
+++ b/library/std/src/sys/unsupported/thread.rs
@@ -1,9 +1,9 @@
-use super::{unsupported, Void};
+use super::unsupported;
 use crate::ffi::CStr;
 use crate::io;
 use crate::time::Duration;
 
-pub struct Thread(Void);
+pub struct Thread(!);
 
 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
@@ -26,7 +26,7 @@ impl Thread {
     }
 
     pub fn join(self) {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/vxworks/env.rs b/library/std/src/sys/vxworks/env.rs
deleted file mode 100644
index fe1aedd58590b..0000000000000
--- a/library/std/src/sys/vxworks/env.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
-    pub const FAMILY: &str = "vxworks";
-    pub const OS: &str = "vxworks";
-    pub const DLL_PREFIX: &str = "lib";
-    pub const DLL_SUFFIX: &str = ".so";
-    pub const DLL_EXTENSION: &str = "so";
-    pub const EXE_SUFFIX: &str = "";
-    pub const EXE_EXTENSION: &str = "";
-}
diff --git a/library/std/src/sys/vxworks/mod.rs b/library/std/src/sys/vxworks/mod.rs
deleted file mode 100644
index 12d0147a12981..0000000000000
--- a/library/std/src/sys/vxworks/mod.rs
+++ /dev/null
@@ -1,138 +0,0 @@
-#![allow(dead_code)]
-#![allow(missing_docs, nonstandard_style)]
-
-use crate::io::ErrorKind;
-
-pub use self::rand::hashmap_random_keys;
-pub use crate::os::vxworks as platform;
-pub use libc::strlen;
-
-#[macro_use]
-#[path = "../unix/weak.rs"]
-pub mod weak;
-
-#[path = "../unix/alloc.rs"]
-pub mod alloc;
-#[path = "../unix/args.rs"]
-pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
-#[path = "../unix/condvar.rs"]
-pub mod condvar;
-pub mod env;
-#[path = "../unix/ext/mod.rs"]
-pub mod ext;
-#[path = "../unix/fd.rs"]
-pub mod fd;
-#[path = "../unix/fs.rs"]
-pub mod fs;
-#[path = "../unix/io.rs"]
-pub mod io;
-#[path = "../unix/memchr.rs"]
-pub mod memchr;
-#[path = "../unix/mutex.rs"]
-pub mod mutex;
-#[path = "../unix/net.rs"]
-pub mod net;
-#[path = "../unix/os.rs"]
-pub mod os;
-#[path = "../unix/path.rs"]
-pub mod path;
-#[path = "../unix/pipe.rs"]
-pub mod pipe;
-pub mod process;
-pub mod rand;
-#[path = "../unix/rwlock.rs"]
-pub mod rwlock;
-#[path = "../unix/stack_overflow.rs"]
-pub mod stack_overflow;
-#[path = "../unix/stdio.rs"]
-pub mod stdio;
-#[path = "../unix/thread.rs"]
-pub mod thread;
-pub mod thread_local_dtor;
-#[path = "../unix/thread_local_key.rs"]
-pub mod thread_local_key;
-#[path = "../unix/time.rs"]
-pub mod time;
-
-pub use crate::sys_common::os_str_bytes as os_str;
-
-#[cfg(not(test))]
-pub fn init() {
-    // ignore SIGPIPE
-    unsafe {
-        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
-    }
-}
-
-pub use libc::signal;
-
-pub fn decode_error_kind(errno: i32) -> ErrorKind {
-    match errno as libc::c_int {
-        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
-        libc::ECONNRESET => ErrorKind::ConnectionReset,
-        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
-        libc::EPIPE => ErrorKind::BrokenPipe,
-        libc::ENOTCONN => ErrorKind::NotConnected,
-        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
-        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
-        libc::EADDRINUSE => ErrorKind::AddrInUse,
-        libc::ENOENT => ErrorKind::NotFound,
-        libc::EINTR => ErrorKind::Interrupted,
-        libc::EINVAL => ErrorKind::InvalidInput,
-        libc::ETIMEDOUT => ErrorKind::TimedOut,
-        libc::EEXIST => ErrorKind::AlreadyExists,
-        libc::ENOSYS => ErrorKind::Unsupported,
-
-        // These two constants can have the same value on some systems,
-        // but different values on others, so we can't use a match
-        // clause
-        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,
-
-        _ => ErrorKind::Other,
-    }
-}
-
-#[doc(hidden)]
-pub trait IsMinusOne {
-    fn is_minus_one(&self) -> bool;
-}
-
-macro_rules! impl_is_minus_one {
-    ($($t:ident)*) => ($(impl IsMinusOne for $t {
-        fn is_minus_one(&self) -> bool {
-            *self == -1
-        }
-    })*)
-}
-
-impl_is_minus_one! { i8 i16 i32 i64 isize }
-
-pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
-    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
-}
-
-pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
-where
-    T: IsMinusOne,
-    F: FnMut() -> T,
-{
-    loop {
-        match cvt(f()) {
-            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
-            other => return other,
-        }
-    }
-}
-
-// 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
-// output will be printed.  Additionally the shell will generally print a more
-// understandable error message like "Abort trap" rather than "Illegal
-// instruction" that intrinsics::abort would cause, as intrinsics::abort is
-// implemented as an illegal instruction.
-pub fn abort_internal() -> ! {
-    unsafe { libc::abort() }
-}
diff --git a/library/std/src/sys/vxworks/process/mod.rs b/library/std/src/sys/vxworks/process/mod.rs
deleted file mode 100644
index dc6130eaa24a8..0000000000000
--- a/library/std/src/sys/vxworks/process/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes};
-pub use self::process_inner::{ExitStatus, Process};
-pub use crate::ffi::OsString as EnvKey;
-pub use crate::sys_common::process::CommandEnvs;
-
-#[path = "../../unix/process/process_common.rs"]
-mod process_common;
-#[path = "process_vxworks.rs"]
-mod process_inner;
diff --git a/library/std/src/sys/vxworks/rand.rs b/library/std/src/sys/vxworks/rand.rs
deleted file mode 100644
index 3a1ff5fd3b9c6..0000000000000
--- a/library/std/src/sys/vxworks/rand.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use crate::mem;
-use crate::slice;
-
-pub fn hashmap_random_keys() -> (u64, u64) {
-    let mut v = (0, 0);
-    unsafe {
-        let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8, mem::size_of_val(&v));
-        imp::fill_bytes(view);
-    }
-    return v;
-}
-
-mod imp {
-    use crate::io;
-    use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
-
-    pub fn fill_bytes(v: &mut [u8]) {
-        static RNG_INIT: AtomicBool = AtomicBool::new(false);
-        while !RNG_INIT.load(Relaxed) {
-            let ret = unsafe { libc::randSecure() };
-            if ret < 0 {
-                panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
-            } else if ret > 0 {
-                RNG_INIT.store(true, Relaxed);
-                break;
-            }
-            unsafe { libc::usleep(10) };
-        }
-        let ret = unsafe {
-            libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
-        };
-        if ret < 0 {
-            panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
-        }
-    }
-}
diff --git a/library/std/src/sys/vxworks/thread_local_dtor.rs b/library/std/src/sys/vxworks/thread_local_dtor.rs
deleted file mode 100644
index 5391ed83ebc36..0000000000000
--- a/library/std/src/sys/vxworks/thread_local_dtor.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![cfg(target_thread_local)]
-#![unstable(feature = "thread_local_internals", issue = "none")]
-
-pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
-    use crate::sys_common::thread_local_dtor::register_dtor_fallback;
-    register_dtor_fallback(t, dtor);
-}
diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs
index 3f294e7df418e..06860673d90e0 100644
--- a/library/std/src/sys/wasi/net.rs
+++ b/library/std/src/sys/wasi/net.rs
@@ -5,7 +5,7 @@ use crate::convert::TryFrom;
 use crate::fmt;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::sys_common::FromInner;
 use crate::time::Duration;
 
@@ -343,18 +343,18 @@ impl fmt::Debug for UdpSocket {
     }
 }
 
-pub struct LookupHost(Void);
+pub struct LookupHost(!);
 
 impl LookupHost {
     pub fn port(&self) -> u16 {
-        match self.0 {}
+        self.0
     }
 }
 
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index 185d6109cb93e..cf17ac0ba5f2b 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -10,7 +10,7 @@ use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sys::memchr;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::vec;
 
 // Add a few symbols not in upstream `libc` just yet.
@@ -87,7 +87,7 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
     }
 }
 
-pub struct SplitPaths<'a>(&'a Void);
+pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
 
 pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
     panic!("unsupported")
@@ -96,7 +96,7 @@ pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
 impl<'a> Iterator for SplitPaths<'a> {
     type Item = PathBuf;
     fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/wasi/thread.rs b/library/std/src/sys/wasi/thread.rs
index 8eaa5f09cb656..74515553a8218 100644
--- a/library/std/src/sys/wasi/thread.rs
+++ b/library/std/src/sys/wasi/thread.rs
@@ -3,10 +3,10 @@
 use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::time::Duration;
 
-pub struct Thread(Void);
+pub struct Thread(!);
 
 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
@@ -59,7 +59,7 @@ impl Thread {
     }
 
     pub fn join(self) {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/wasm/thread.rs b/library/std/src/sys/wasm/thread.rs
index 5eafb77da1dcd..b7bf95c89b482 100644
--- a/library/std/src/sys/wasm/thread.rs
+++ b/library/std/src/sys/wasm/thread.rs
@@ -1,9 +1,9 @@
 use crate::ffi::CStr;
 use crate::io;
-use crate::sys::{unsupported, Void};
+use crate::sys::unsupported;
 use crate::time::Duration;
 
-pub struct Thread(Void);
+pub struct Thread(!);
 
 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
 
@@ -47,7 +47,7 @@ impl Thread {
     }
 
     pub fn join(self) {
-        match self.0 {}
+        self.0
     }
 }
 
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 3e4176ef7f8fe..eb4b3af144c85 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -287,6 +287,8 @@ pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
 
 pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
 
+pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
@@ -687,9 +689,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
     pub const TOKEN_READ: DWORD = 0x20008;
 
     extern "system" {
-        #[link_name = "SystemFunction036"]
-        pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
-
         pub fn ReadConsoleW(hConsoleInput: HANDLE,
                             lpBuffer: LPVOID,
                             nNumberOfCharsToRead: DWORD,
@@ -731,8 +730,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
 // UWP specific functions & types
 cfg_if::cfg_if! {
 if #[cfg(target_vendor = "uwp")] {
-    pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
-
     #[repr(C)]
     pub struct FILE_STANDARD_INFO {
         pub AllocationSize: LARGE_INTEGER,
@@ -747,8 +744,6 @@ if #[cfg(target_vendor = "uwp")] {
                                             fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
                                             lpFileInformation: LPVOID,
                                             dwBufferSize: DWORD) -> BOOL;
-        pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8,
-                               cbBuffer: ULONG, dwFlags: ULONG) -> LONG;
     }
 }
 }
@@ -1068,6 +1063,15 @@ extern "system" {
     pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
     pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
     pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
+
+    // >= Vista / Server 2008
+    // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+    pub fn BCryptGenRandom(
+        hAlgorithm: LPVOID,
+        pBuffer: *mut u8,
+        cbBuffer: ULONG,
+        dwFlags: ULONG,
+    ) -> NTSTATUS;
 }
 
 // Functions that aren't available on every version of Windows that we support,
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index 973301af2d992..5ca36264cee69 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -276,13 +276,13 @@ pub fn abort_internal() -> ! {
 cfg_if::cfg_if! {
     if #[cfg(target_vendor = "uwp")] {
         #[link(name = "ws2_32")]
-        // For BCryptGenRandom
-        #[link(name = "bcrypt")]
+        #[link(name = "bcrypt")] // For BCryptGenRandom
         extern "C" {}
     } else {
         #[link(name = "advapi32")]
         #[link(name = "ws2_32")]
         #[link(name = "userenv")]
+        #[link(name = "bcrypt")] // For BCryptGenRandom
         extern "C" {}
     }
 }
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index 87ea416bf675a..de73e9154b45e 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -2,18 +2,6 @@ use crate::io;
 use crate::mem;
 use crate::sys::c;
 
-#[cfg(not(target_vendor = "uwp"))]
-pub fn hashmap_random_keys() -> (u64, u64) {
-    let mut v = (0, 0);
-    let ret =
-        unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
-    if ret == 0 {
-        panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
-    }
-    v
-}
-
-#[cfg(target_vendor = "uwp")]
 pub fn hashmap_random_keys() -> (u64, u64) {
     use crate::ptr;
 
diff --git a/library/std/src/sys_common/poison.rs b/library/std/src/sys_common/poison.rs
index 2ab2c700a1bf1..1f71187f1b466 100644
--- a/library/std/src/sys_common/poison.rs
+++ b/library/std/src/sys_common/poison.rs
@@ -127,7 +127,7 @@ pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for PoisonError<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "PoisonError { inner: .. }".fmt(f)
+        f.debug_struct("PoisonError").finish_non_exhaustive()
     }
 }
 
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 3dcf7e334531f..abd5b7784834c 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -100,7 +100,7 @@ pub struct LocalKey<T: 'static> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T: 'static> fmt::Debug for LocalKey<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("LocalKey { .. }")
+        f.debug_struct("LocalKey").finish_non_exhaustive()
     }
 }
 
@@ -472,7 +472,7 @@ pub mod statik {
 
     impl<T> fmt::Debug for Key<T> {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            f.pad("Key { .. }")
+            f.debug_struct("Key").finish_non_exhaustive()
         }
     }
 
@@ -537,7 +537,7 @@ pub mod fast {
 
     impl<T> fmt::Debug for Key<T> {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            f.pad("Key { .. }")
+            f.debug_struct("Key").finish_non_exhaustive()
         }
     }
 
@@ -651,7 +651,7 @@ pub mod os {
 
     impl<T> fmt::Debug for Key<T> {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            f.pad("Key { .. }")
+            f.debug_struct("Key").finish_non_exhaustive()
         }
     }
 
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 54e39f762741f..30d8c2a1b6fa0 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1413,7 +1413,7 @@ impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl<T> fmt::Debug for JoinHandle<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.pad("JoinHandle { .. }")
+        f.debug_struct("JoinHandle").finish_non_exhaustive()
     }
 }
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 87f8cf160e001..a32b92ef1af83 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -470,12 +470,16 @@ impl Step for Std {
         // Look for library/std, library/core etc in the `x.py doc` arguments and
         // open the corresponding rendered docs.
         for path in builder.paths.iter().map(components_simplified) {
-            if path.get(0) == Some(&"library") {
-                let requested_crate = &path[1];
-                if krates.contains(&requested_crate) {
-                    let index = out.join(requested_crate).join("index.html");
-                    open(builder, &index);
-                }
+            let requested_crate = if path.get(0) == Some(&"library") {
+                &path[1]
+            } else if !path.is_empty() {
+                &path[0]
+            } else {
+                continue;
+            };
+            if krates.contains(&requested_crate) {
+                let index = out.join(requested_crate).join("index.html");
+                open(builder, &index);
             }
         }
     }
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 22780804610b6..86bedb51538b5 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -191,7 +191,7 @@ mechanisms of the compiler. This is often mapped to GCC's personality function
 which do not trigger a panic can be assured that this function is never
 called. The language item's name is `eh_personality`.
 
-[unwind]: https://github.com/rust-lang/rust/blob/master/src/libpanic_unwind/gcc.rs
+[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
 
 The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
 compiler. When a panic happens, this controls the message that's displayed on
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 05d2001385929..0aa7aa763c2af 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -167,19 +167,18 @@ impl<'tcx> Context<'tcx> {
         "../".repeat(self.current.len())
     }
 
-    fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
-        let mut title = if it.is_primitive() || it.is_keyword() {
-            // No need to include the namespace for primitive types and keywords
-            String::new()
-        } else {
-            self.current.join("::")
-        };
-        if pushname {
-            if !title.is_empty() {
-                title.push_str("::");
-            }
+    fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
+        let mut title = String::new();
+        if !is_module {
             title.push_str(&it.name.unwrap().as_str());
         }
+        if !it.is_primitive() && !it.is_keyword() {
+            if !is_module {
+                title.push_str(" in ");
+            }
+            // No need to include the namespace for primitive types and keywords
+            title.push_str(&self.current.join("::"));
+        };
         title.push_str(" - Rust");
         let tyname = it.type_();
         let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(&doc));
@@ -598,7 +597,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
         info!("Recursing into {}", self.dst.display());
 
-        let buf = self.render_item(item, false);
+        let buf = self.render_item(item, true);
         // buf will be empty if the module is stripped and there is no redirect for it
         if !buf.is_empty() {
             self.shared.ensure_dir(&self.dst)?;
@@ -641,7 +640,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             self.render_redirect_pages = item.is_stripped();
         }
 
-        let buf = self.render_item(&item, true);
+        let buf = self.render_item(&item, false);
         // buf will be empty if the item is stripped and there is no redirect for it
         if !buf.is_empty() {
             let name = item.name.as_ref().unwrap();
diff --git a/src/test/rustdoc/prim-title.rs b/src/test/rustdoc/prim-title.rs
deleted file mode 100644
index fa3fd512fada6..0000000000000
--- a/src/test/rustdoc/prim-title.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_name = "foo"]
-
-// @has foo/primitive.u8.html '//head/title' 'u8 - Rust'
-// @!has - '//head/title' 'foo'
-#[doc(primitive = "u8")]
-/// `u8` docs
-mod u8 {}
diff --git a/src/test/rustdoc/tab_title.rs b/src/test/rustdoc/tab_title.rs
new file mode 100644
index 0000000000000..7dce6092deaed
--- /dev/null
+++ b/src/test/rustdoc/tab_title.rs
@@ -0,0 +1,44 @@
+#![crate_name = "foo"]
+#![feature(doc_keyword)]
+
+// tests for the html <title> element
+
+// @has foo/index.html '//head/title' 'foo - Rust'
+
+// @has foo/fn.widget_count.html '//head/title' 'widget_count in foo - Rust'
+/// blah
+pub fn widget_count() {}
+
+// @has foo/struct.Widget.html '//head/title' 'Widget in foo - Rust'
+pub struct Widget;
+
+// @has foo/constant.ANSWER.html '//head/title' 'ANSWER in foo - Rust'
+pub const ANSWER: u8 = 42;
+
+// @has foo/blah/index.html '//head/title' 'foo::blah - Rust'
+pub mod blah {
+    // @has foo/blah/struct.Widget.html '//head/title' 'Widget in foo::blah - Rust'
+    pub struct Widget;
+
+    // @has foo/blah/trait.Awesome.html '//head/title' 'Awesome in foo::blah - Rust'
+    pub trait Awesome {}
+
+    // @has foo/blah/fn.make_widget.html '//head/title' 'make_widget in foo::blah - Rust'
+    pub fn make_widget() {}
+
+    // @has foo/macro.cool_macro.html '//head/title' 'cool_macro in foo - Rust'
+    #[macro_export]
+    macro_rules! cool_macro {
+        ($t:tt) => { $t }
+    }
+}
+
+// @has foo/keyword.continue.html '//head/title' 'continue - Rust'
+#[doc(keyword = "continue")]
+mod continue_keyword {}
+
+// @has foo/primitive.u8.html '//head/title' 'u8 - Rust'
+// @!has - '//head/title' 'foo'
+#[doc(primitive = "u8")]
+/// `u8` docs
+mod u8 {}
diff --git a/src/test/ui/associated-type-bounds/issue-79949.rs b/src/test/ui/associated-type-bounds/issue-79949.rs
new file mode 100644
index 0000000000000..9f924f1fd81d8
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/issue-79949.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(associated_type_bounds)]
+#![feature(generic_associated_types)]
+
+trait MP {
+    type T<'a>;
+}
+struct S(String);
+impl MP for S {
+    type T<'a> = &'a str;
+}
+
+trait SR: MP {
+    fn sr<IM>(&self) -> i32
+    where
+        for<'a> IM: T<T: U<<Self as MP>::T<'a>>>;
+}
+
+trait T {
+    type T;
+}
+trait U<X> {}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-70303.rs b/src/test/ui/generic-associated-types/issue-70303.rs
new file mode 100644
index 0000000000000..a1cb2295b639e
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-70303.rs
@@ -0,0 +1,60 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Document {
+    type Cursor<'a>: DocCursor<'a>;
+
+    fn cursor(&self) -> Self::Cursor<'_>;
+}
+
+struct DocumentImpl {}
+
+impl Document for DocumentImpl {
+    type Cursor<'a> = DocCursorImpl<'a>;
+
+    fn cursor(&self) -> Self::Cursor<'_> {
+        DocCursorImpl {
+            document: &self,
+        }
+    }
+}
+
+
+trait DocCursor<'a> {}
+
+struct DocCursorImpl<'a> {
+    document: &'a DocumentImpl,
+}
+
+impl<'a> DocCursor<'a> for DocCursorImpl<'a> {}
+
+struct Lexer<'d, Cursor>
+where
+    Cursor: DocCursor<'d>,
+{
+    cursor: Cursor,
+    _phantom: std::marker::PhantomData<&'d ()>,
+}
+
+
+impl<'d, Cursor> Lexer<'d, Cursor>
+where
+    Cursor: DocCursor<'d>,
+{
+    pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor>
+    where
+        Doc: Document<Cursor<'d> = Cursor>,
+    {
+        Lexer {
+            cursor: document.cursor(),
+            _phantom: std::marker::PhantomData,
+        }
+    }
+}
+
+pub fn main() {
+    let doc = DocumentImpl {};
+    let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
+}
diff --git a/src/test/ui/generic-associated-types/issue-70304.rs b/src/test/ui/generic-associated-types/issue-70304.rs
new file mode 100644
index 0000000000000..225f61d132ee6
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-70304.rs
@@ -0,0 +1,63 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Document {
+    type Cursor<'a>: DocCursor<'a>;
+
+    fn cursor(&self) -> Self::Cursor<'_>;
+}
+
+struct DocumentImpl {}
+
+impl Document for DocumentImpl {
+    type Cursor<'a> = DocCursorImpl<'a>;
+
+    fn cursor(&self) -> Self::Cursor<'_> {
+        DocCursorImpl {
+            document: &self,
+        }
+    }
+}
+
+
+trait DocCursor<'a> {}
+
+struct DocCursorImpl<'a> {
+    document: &'a DocumentImpl,
+}
+
+impl<'a> DocCursor<'a> for DocCursorImpl<'a> {}
+
+struct Lexer<'d, Cursor>
+where
+    Cursor: DocCursor<'d>,
+{
+    cursor: Cursor,
+    _phantom: std::marker::PhantomData<&'d ()>,
+}
+
+
+impl<'d, Cursor> Lexer<'d, Cursor>
+where
+    Cursor: DocCursor<'d>,
+{
+    pub fn from<Doc>(document: &'d Doc) -> Lexer<'d, Cursor>
+    where
+        Doc: Document<Cursor<'d> = Cursor>,
+    {
+        Lexer {
+            cursor: document.cursor(),
+            _phantom: std::marker::PhantomData,
+        }
+    }
+}
+
+fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
+                                       //~^ ERROR: missing lifetime specifier
+    DocumentImpl {}
+}
+
+pub fn main() {
+    let doc = create_doc();
+    let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc);
+}
diff --git a/src/test/ui/generic-associated-types/issue-70304.stderr b/src/test/ui/generic-associated-types/issue-70304.stderr
new file mode 100644
index 0000000000000..dfa86018976dc
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-70304.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-70304.rs:55:41
+   |
+LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
+   |                                         ^^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+   |
+LL | fn create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> {
+   |                                         ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/generic-associated-types/issue-71176.rs b/src/test/ui/generic-associated-types/issue-71176.rs
new file mode 100644
index 0000000000000..470476bf476a0
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-71176.rs
@@ -0,0 +1,21 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Provider {
+    type A<'a>;
+      //~^ ERROR: missing generics for associated type
+}
+
+impl Provider for () {
+    type A<'a> = ();
+}
+
+struct Holder<B> {
+  inner: Box<dyn Provider<A = B>>,
+}
+
+fn main() {
+    Holder {
+        inner: Box::new(()),
+    };
+}
diff --git a/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr
new file mode 100644
index 0000000000000..dd19dd4ad8e83
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-71176.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `Provider::A`
+  --> $DIR/issue-71176.rs:5:10
+   |
+LL |     type A<'a>;
+   |          ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-71176.rs:5:10
+   |
+LL |     type A<'a>;
+   |          ^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type A<'a><'a>;
+   |           ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs
new file mode 100644
index 0000000000000..1b02aac8bcb24
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-78671.rs
@@ -0,0 +1,14 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait CollectionFamily {
+    type Member<T>;
+         //~^ ERROR: missing generics for associated type
+}
+fn floatify() {
+    Box::new(Family) as &dyn CollectionFamily<Member=usize>
+}
+
+struct Family;
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr
new file mode 100644
index 0000000000000..7a9aced5beab8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-78671.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `CollectionFamily::Member`
+  --> $DIR/issue-78671.rs:5:10
+   |
+LL |     type Member<T>;
+   |          ^^^^^^ expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `T`
+  --> $DIR/issue-78671.rs:5:10
+   |
+LL |     type Member<T>;
+   |          ^^^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     type Member<T><T>;
+   |                ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/issue-79636-1.rs b/src/test/ui/generic-associated-types/issue-79636-1.rs
new file mode 100644
index 0000000000000..17f9387e29204
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79636-1.rs
@@ -0,0 +1,24 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait Monad {
+    type Unwrapped;
+    type Wrapped<B>;
+         //~^ ERROR: missing generics for associated type `Monad::Wrapped`
+
+    fn bind<B, F>(self, f: F) -> Self::Wrapped<B> {
+        todo!()
+    }
+}
+
+fn join<MOuter, MInner, A>(outer: MOuter) -> MOuter::Wrapped<A>
+where
+    MOuter: Monad<Unwrapped = MInner>,
+    MInner: Monad<Unwrapped = A, Wrapped = MOuter::Wrapped<A>>,
+{
+    outer.bind(|inner| inner)
+}
+
+fn main() {
+    assert_eq!(join(Some(Some(true))), Some(true));
+}
diff --git a/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr
new file mode 100644
index 0000000000000..58eeb43f70d66
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79636-1.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `Monad::Wrapped`
+  --> $DIR/issue-79636-1.rs:6:10
+   |
+LL |     type Wrapped<B>;
+   |          ^^^^^^^ expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `B`
+  --> $DIR/issue-79636-1.rs:6:10
+   |
+LL |     type Wrapped<B>;
+   |          ^^^^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     type Wrapped<B><B>;
+   |                 ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/issue-79636-2.rs b/src/test/ui/generic-associated-types/issue-79636-2.rs
new file mode 100644
index 0000000000000..5a6542193752b
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79636-2.rs
@@ -0,0 +1,18 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait SomeTrait {
+    type Wrapped<A>: SomeTrait;
+         //~^ ERROR: missing generics for associated type `SomeTrait::Wrapped`
+
+    fn f() -> ();
+}
+
+fn program<W>() -> ()
+where
+    W: SomeTrait<Wrapped = W>,
+{
+    return W::f();
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr
new file mode 100644
index 0000000000000..d5e3c56ebb9ef
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79636-2.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `SomeTrait::Wrapped`
+  --> $DIR/issue-79636-2.rs:5:10
+   |
+LL |     type Wrapped<A>: SomeTrait;
+   |          ^^^^^^^ expected 1 type argument
+   |
+note: associated type defined here, with 1 type parameter: `A`
+  --> $DIR/issue-79636-2.rs:5:10
+   |
+LL |     type Wrapped<A>: SomeTrait;
+   |          ^^^^^^^ -
+help: use angle brackets to add missing type argument
+   |
+LL |     type Wrapped<A><A>: SomeTrait;
+   |                 ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.