about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_driver/src/lib.rs7
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs4
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs20
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_target/src/spec/android_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/mod.rs7
-rw-r--r--library/std/src/ffi/c_str.rs2
-rw-r--r--library/std/src/fs.rs5
-rw-r--r--library/std/src/io/buffered/bufwriter.rs4
-rw-r--r--library/std/src/io/cursor.rs8
-rw-r--r--library/std/src/io/error.rs26
-rw-r--r--library/std/src/io/error/tests.rs16
-rw-r--r--library/std/src/io/impls.rs4
-rw-r--r--library/std/src/io/mod.rs16
-rw-r--r--library/std/src/io/tests.rs4
-rw-r--r--library/std/src/net/mod.rs2
-rw-r--r--library/std/src/net/udp.rs2
-rw-r--r--library/std/src/sys/hermit/fd.rs6
-rw-r--r--library/std/src/sys/hermit/fs.rs12
-rw-r--r--library/std/src/sys/hermit/mod.rs5
-rw-r--r--library/std/src/sys/hermit/net.rs140
-rw-r--r--library/std/src/sys/hermit/stdio.rs8
-rw-r--r--library/std/src/sys/hermit/thread.rs2
-rw-r--r--library/std/src/sys/sgx/mod.rs6
-rw-r--r--library/std/src/sys/sgx/net.rs12
-rw-r--r--library/std/src/sys/unix/android.rs6
-rw-r--r--library/std/src/sys/unix/ext/fs.rs6
-rw-r--r--library/std/src/sys/unix/ext/net/addr.rs12
-rw-r--r--library/std/src/sys/unix/fs.rs12
-rw-r--r--library/std/src/sys/unix/l4re.rs2
-rw-r--r--library/std/src/sys/unix/net.rs15
-rw-r--r--library/std/src/sys/unix/os.rs18
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs17
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs14
-rw-r--r--library/std/src/sys/unsupported/common.rs2
-rw-r--r--library/std/src/sys/unsupported/os.rs4
-rw-r--r--library/std/src/sys/vxworks/process/process_vxworks.rs9
-rw-r--r--library/std/src/sys/wasi/ext/fs.rs8
-rw-r--r--library/std/src/sys/wasi/fs.rs2
-rw-r--r--library/std/src/sys/windows/fs.rs6
-rw-r--r--library/std/src/sys/windows/mod.rs4
-rw-r--r--library/std/src/sys/windows/net.rs12
-rw-r--r--library/std/src/sys/windows/process.rs2
-rw-r--r--library/std/src/sys/windows/stdio.rs12
-rw-r--r--library/std/src/sys_common/fs.rs4
-rw-r--r--library/std/src/sys_common/net.rs4
-rw-r--r--library/std/src/thread/available_concurrency.rs10
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/core.rs28
-rw-r--r--src/librustdoc/doctree.rs4
-rw-r--r--src/librustdoc/fold.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/formats/renderer.rs20
-rw-r--r--src/librustdoc/html/render/cache.rs7
-rw-r--r--src/librustdoc/html/render/context.rs53
-rw-r--r--src/librustdoc/html/render/mod.rs8
-rw-r--r--src/librustdoc/html/static/rustdoc.css11
-rw-r--r--src/librustdoc/html/static/themes/dark.css4
-rw-r--r--src/librustdoc/html/static/themes/light.css4
-rw-r--r--src/librustdoc/json/mod.rs4
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs8
-rw-r--r--src/librustdoc/visit_ast.rs14
-rw-r--r--src/test/codegen/default-requires-uwtable.rs15
-rw-r--r--src/test/codegen/force-no-unwind-tables.rs7
-rw-r--r--src/test/incremental/ich_nested_items.rs1
-rw-r--r--src/test/incremental/ich_resolve_results.rs1
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs2
-rw-r--r--src/test/rustdoc-gui/check_info_sign_position.goml9
-rw-r--r--src/test/rustdoc-gui/lib.rs27
-rw-r--r--src/test/rustdoc-gui/trait-sidebar-item-order.goml7
-rw-r--r--src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs6
-rw-r--r--src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr11
-rw-r--r--src/test/ui/dep-graph/dep-graph-check-attr.rs20
-rw-r--r--src/test/ui/dep-graph/dep-graph-check-attr.stderr26
77 files changed, 522 insertions, 295 deletions
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 25a78041c00..e527d55fc2a 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -895,7 +895,12 @@ Available lint options:
     let print_lints = |lints: Vec<&Lint>| {
         for lint in lints {
             let name = lint.name_lower().replace("_", "-");
-            println!("    {}  {:7.7}  {}", padded(&name), lint.default_level.as_str(), lint.desc);
+            println!(
+                "    {}  {:7.7}  {}",
+                padded(&name),
+                lint.default_level(sess.edition()).as_str(),
+                lint.desc
+            );
         }
         println!("\n");
     };
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index f1f69f1510b..a080b0ce339 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -57,6 +57,10 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
             dump_graph(tcx);
         }
 
+        if !tcx.sess.opts.debugging_opts.query_dep_graph {
+            return;
+        }
+
         // if the `rustc_attrs` feature is not enabled, then the
         // attributes we are interested in cannot be present anyway, so
         // skip the walk.
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 0b544b8ab41..cb089a728ee 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -148,6 +148,10 @@ impl Assertion {
 }
 
 pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
+    if !tcx.sess.opts.debugging_opts.query_dep_graph {
+        return;
+    }
+
     // can't add `#[rustc_dirty]` etc without opting in to this feature
     if !tcx.features().rustc_attrs {
         return;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index d91d0e1765b..85add83f88b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -99,6 +99,12 @@ impl CheckAttrVisitor<'tcx> {
                 self.check_naked(hir_id, attr, span, target)
             } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) {
                 self.check_rustc_legacy_const_generics(&attr, span, target, item)
+            } else if self.tcx.sess.check_name(attr, sym::rustc_clean)
+                || self.tcx.sess.check_name(attr, sym::rustc_dirty)
+                || self.tcx.sess.check_name(attr, sym::rustc_if_this_changed)
+                || self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need)
+            {
+                self.check_rustc_dirty_clean(&attr)
             } else {
                 // lint-only checks
                 if self.tcx.sess.check_name(attr, sym::cold) {
@@ -1012,6 +1018,20 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
+    /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph
+    /// option is passed to the compiler.
+    fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
+        if self.tcx.sess.opts.debugging_opts.query_dep_graph {
+            true
+        } else {
+            self.tcx
+                .sess
+                .struct_span_err(attr.span, "attribute requires -Z query-dep-graph to be enabled")
+                .emit();
+            false
+        }
+    }
+
     /// Checks if `#[link_section]` is applied to a function or static.
     fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
         match target {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index fc57b6b8ace..203af36b053 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -863,7 +863,7 @@ impl Session {
         } else if self.target.requires_uwtable {
             true
         } else {
-            self.opts.cg.force_unwind_tables.unwrap_or(false)
+            self.opts.cg.force_unwind_tables.unwrap_or(self.target.default_uwtable)
         }
     }
 
diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs
index f6fbe7cd5f6..c7d2f2329ee 100644
--- a/compiler/rustc_target/src/spec/android_base.rs
+++ b/compiler/rustc_target/src/spec/android_base.rs
@@ -12,7 +12,10 @@ pub fn opts() -> TargetOptions {
     base.dwarf_version = Some(2);
     base.position_independent_executables = true;
     base.has_elf_tls = false;
-    base.requires_uwtable = true;
+    // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
+    // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
+    // was to always emit `uwtable`).
+    base.default_uwtable = true;
     base.crt_static_respected = false;
     base
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c9fffd213d7..ddfd8262522 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1111,6 +1111,10 @@ pub struct TargetOptions {
     /// unwinders.
     pub requires_uwtable: bool,
 
+    /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables`
+    /// is not specified and `uwtable` is not required on this target.
+    pub default_uwtable: bool,
+
     /// Whether or not SIMD types are passed by reference in the Rust ABI,
     /// typically required if a target can be compiled with a mixed set of
     /// target features. This is `true` by default, and `false` for targets like
@@ -1248,6 +1252,7 @@ impl Default for TargetOptions {
             default_hidden_visibility: false,
             emit_debug_gdb_scripts: true,
             requires_uwtable: false,
+            default_uwtable: false,
             simd_types_indirect: true,
             limit_rdylib_exports: true,
             override_export_symbols: None,
@@ -1711,6 +1716,7 @@ impl Target {
         key!(default_hidden_visibility, bool);
         key!(emit_debug_gdb_scripts, bool);
         key!(requires_uwtable, bool);
+        key!(default_uwtable, bool);
         key!(simd_types_indirect, bool);
         key!(limit_rdylib_exports, bool);
         key!(override_export_symbols, opt_list);
@@ -1947,6 +1953,7 @@ impl ToJson for Target {
         target_option_val!(default_hidden_visibility);
         target_option_val!(emit_debug_gdb_scripts);
         target_option_val!(requires_uwtable);
+        target_option_val!(default_uwtable);
         target_option_val!(simd_types_indirect);
         target_option_val!(limit_rdylib_exports);
         target_option_val!(override_export_symbols);
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 945bfda1b78..687ed61b959 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -1036,7 +1036,7 @@ impl fmt::Display for NulError {
 impl From<NulError> for io::Error {
     /// Converts a [`NulError`] into a [`io::Error`].
     fn from(_: NulError) -> io::Error {
-        io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
+        io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte")
     }
 }
 
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 43119c36cfe..ccbc69a975c 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2188,7 +2188,10 @@ impl DirBuilder {
         match path.parent() {
             Some(p) => self.create_dir_all(p)?,
             None => {
-                return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree"));
+                return Err(io::Error::new_const(
+                    io::ErrorKind::Other,
+                    &"failed to create whole tree",
+                ));
             }
         }
         match self.inner.mkdir(path) {
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 65bc2fcf00a..80f98bbbad3 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -164,9 +164,9 @@ impl<W: Write> BufWriter<W> {
 
             match r {
                 Ok(0) => {
-                    return Err(Error::new(
+                    return Err(Error::new_const(
                         ErrorKind::WriteZero,
-                        "failed to write the buffered data",
+                        &"failed to write the buffered data",
                     ));
                 }
                 Ok(n) => guard.consume(n),
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index bbee2cc9842..9021b470065 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -229,9 +229,9 @@ where
                 self.pos = n;
                 Ok(self.pos)
             }
-            None => Err(Error::new(
+            None => Err(Error::new_const(
                 ErrorKind::InvalidInput,
-                "invalid seek to a negative or overflowing position",
+                &"invalid seek to a negative or overflowing position",
             )),
         }
     }
@@ -328,9 +328,9 @@ fn slice_write_vectored(
 // Resizing write implementation
 fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
     let pos: usize = (*pos_mut).try_into().map_err(|_| {
-        Error::new(
+        Error::new_const(
             ErrorKind::InvalidInput,
-            "cursor position exceeds maximum possible vector length",
+            &"cursor position exceeds maximum possible vector length",
         )
     })?;
     // Make sure the internal buffer is as least as big as where we
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index ba0f0a0cd71..2122aa755e1 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -69,6 +69,8 @@ impl fmt::Debug for Error {
 enum Repr {
     Os(i32),
     Simple(ErrorKind),
+    // &str is a fat pointer, but &&str is a thin pointer.
+    SimpleMessage(ErrorKind, &'static &'static str),
     Custom(Box<Custom>),
 }
 
@@ -259,6 +261,18 @@ impl Error {
         Error { repr: Repr::Custom(Box::new(Custom { kind, error })) }
     }
 
+    /// Creates a new I/O error from a known kind of error as well as a
+    /// constant message.
+    ///
+    /// This function does not allocate.
+    ///
+    /// This function should maybe change to
+    /// `new_const<const MSG: &'static str>(kind: ErrorKind)`
+    /// in the future, when const generics allow that.
+    pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error {
+        Self { repr: Repr::SimpleMessage(kind, message) }
+    }
+
     /// Returns an error representing the last OS error which occurred.
     ///
     /// This function reads the value of `errno` for the target platform (e.g.
@@ -342,6 +356,7 @@ impl Error {
             Repr::Os(i) => Some(i),
             Repr::Custom(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
         }
     }
 
@@ -377,6 +392,7 @@ impl Error {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
             Repr::Custom(ref c) => Some(&*c.error),
         }
     }
@@ -448,6 +464,7 @@ impl Error {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
             Repr::Custom(ref mut c) => Some(&mut *c.error),
         }
     }
@@ -484,6 +501,7 @@ impl Error {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
             Repr::Custom(c) => Some(c.error),
         }
     }
@@ -512,6 +530,7 @@ impl Error {
             Repr::Os(code) => sys::decode_error_kind(code),
             Repr::Custom(ref c) => c.kind,
             Repr::Simple(kind) => kind,
+            Repr::SimpleMessage(kind, _) => kind,
         }
     }
 }
@@ -527,6 +546,9 @@ impl fmt::Debug for Repr {
                 .finish(),
             Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
             Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
+            Repr::SimpleMessage(kind, &message) => {
+                fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish()
+            }
         }
     }
 }
@@ -541,6 +563,7 @@ impl fmt::Display for Error {
             }
             Repr::Custom(ref c) => c.error.fmt(fmt),
             Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
+            Repr::SimpleMessage(_, &msg) => msg.fmt(fmt),
         }
     }
 }
@@ -551,6 +574,7 @@ impl error::Error for Error {
     fn description(&self) -> &str {
         match self.repr {
             Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
+            Repr::SimpleMessage(_, &msg) => msg,
             Repr::Custom(ref c) => c.error.description(),
         }
     }
@@ -560,6 +584,7 @@ impl error::Error for Error {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
             Repr::Custom(ref c) => c.error.cause(),
         }
     }
@@ -568,6 +593,7 @@ impl error::Error for Error {
         match self.repr {
             Repr::Os(..) => None,
             Repr::Simple(..) => None,
+            Repr::SimpleMessage(..) => None,
             Repr::Custom(ref c) => c.error.source(),
         }
     }
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
index 0cce9368c80..5098a46313d 100644
--- a/library/std/src/io/error/tests.rs
+++ b/library/std/src/io/error/tests.rs
@@ -1,10 +1,16 @@
 use super::{Custom, Error, ErrorKind, Repr};
 use crate::error;
 use crate::fmt;
+use crate::mem::size_of;
 use crate::sys::decode_error_kind;
 use crate::sys::os::error_string;
 
 #[test]
+fn test_size() {
+    assert!(size_of::<Error>() <= size_of::<[usize; 2]>());
+}
+
+#[test]
 fn test_debug_error() {
     let code = 6;
     let msg = error_string(code);
@@ -51,3 +57,13 @@ fn test_downcasting() {
     let extracted = err.into_inner().unwrap();
     extracted.downcast::<TestError>().unwrap();
 }
+
+#[test]
+fn test_const() {
+    const E: Error = Error::new_const(ErrorKind::NotFound, &"hello");
+
+    assert_eq!(E.kind(), ErrorKind::NotFound);
+    assert_eq!(E.to_string(), "hello");
+    assert!(format!("{:?}", E).contains("\"hello\""));
+    assert!(format!("{:?}", E).contains("NotFound"));
+}
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 9870cfc4c95..6891bd8a664 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -263,7 +263,7 @@ impl Read for &[u8] {
     #[inline]
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         if buf.len() > self.len() {
-            return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"));
+            return Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer"));
         }
         let (a, b) = self.split_at(buf.len());
 
@@ -345,7 +345,7 @@ impl Write for &mut [u8] {
         if self.write(data)? == data.len() {
             Ok(())
         } else {
-            Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"))
+            Err(Error::new_const(ErrorKind::WriteZero, &"failed to write whole buffer"))
         }
     }
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 6abb300054a..5316305a303 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -333,7 +333,7 @@ where
         let ret = f(g.buf);
         if str::from_utf8(&g.buf[g.len..]).is_err() {
             ret.and_then(|_| {
-                Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
+                Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8"))
             })
         } else {
             g.len = g.buf.len();
@@ -429,7 +429,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
         }
     }
     if !buf.is_empty() {
-        Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+        Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
     } else {
         Ok(())
     }
@@ -1437,7 +1437,10 @@ pub trait Write {
         while !buf.is_empty() {
             match self.write(buf) {
                 Ok(0) => {
-                    return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
+                    return Err(Error::new_const(
+                        ErrorKind::WriteZero,
+                        &"failed to write whole buffer",
+                    ));
                 }
                 Ok(n) => buf = &buf[n..],
                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
@@ -1502,7 +1505,10 @@ pub trait Write {
         while !bufs.is_empty() {
             match self.write_vectored(bufs) {
                 Ok(0) => {
-                    return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
+                    return Err(Error::new_const(
+                        ErrorKind::WriteZero,
+                        &"failed to write whole buffer",
+                    ));
                 }
                 Ok(n) => bufs = IoSlice::advance(bufs, n),
                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
@@ -1576,7 +1582,7 @@ pub trait Write {
                 if output.error.is_err() {
                     output.error
                 } else {
-                    Err(Error::new(ErrorKind::Other, "formatter error"))
+                    Err(Error::new_const(ErrorKind::Other, &"formatter error"))
                 }
             }
         }
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index a85dd0d9827..2b14e161503 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -152,12 +152,12 @@ fn take_eof() {
 
     impl Read for R {
         fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
-            Err(io::Error::new(io::ErrorKind::Other, ""))
+            Err(io::Error::new_const(io::ErrorKind::Other, &""))
         }
     }
     impl BufRead for R {
         fn fill_buf(&mut self) -> io::Result<&[u8]> {
-            Err(io::Error::new(io::ErrorKind::Other, ""))
+            Err(io::Error::new_const(io::ErrorKind::Other, &""))
         }
         fn consume(&mut self, _amt: usize) {}
     }
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index d4b1552fec5..d814e9b25ba 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -88,6 +88,6 @@ where
         }
     }
     Err(last_err.unwrap_or_else(|| {
-        Error::new(ErrorKind::InvalidInput, "could not resolve to any addresses")
+        Error::new_const(ErrorKind::InvalidInput, &"could not resolve to any addresses")
     }))
 }
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 2377a76a33d..b9af5992dff 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -173,7 +173,7 @@ impl UdpSocket {
     pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
         match addr.to_socket_addrs()?.next() {
             Some(addr) => self.0.send_to(buf, &addr),
-            None => Err(Error::new(ErrorKind::InvalidInput, "no addresses to send data to")),
+            None => Err(Error::new_const(ErrorKind::InvalidInput, &"no addresses to send data to")),
         }
     }
 
diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs
index 97d1a38b41a..1c0515a1503 100644
--- a/library/std/src/sys/hermit/fd.rs
+++ b/library/std/src/sys/hermit/fd.rs
@@ -46,7 +46,7 @@ impl FileDesc {
         self.duplicate_path(&[])
     }
     pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> {
-        Err(io::Error::new(ErrorKind::Other, "duplicate isn't supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"duplicate isn't supported"))
     }
 
     pub fn nonblocking(&self) -> io::Result<bool> {
@@ -54,11 +54,11 @@ impl FileDesc {
     }
 
     pub fn set_cloexec(&self) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "cloexec isn't supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"cloexec isn't supported"))
     }
 
     pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "nonblocking isn't supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"nonblocking isn't supported"))
     }
 }
 
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 1807655e971..0f33282fa83 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -226,7 +226,7 @@ impl OpenOptions {
             (false, _, true) => Ok(O_WRONLY | O_APPEND),
             (true, _, true) => Ok(O_RDWR | O_APPEND),
             (false, false, false) => {
-                Err(io::Error::new(ErrorKind::InvalidInput, "invalid access mode"))
+                Err(io::Error::new_const(ErrorKind::InvalidInput, &"invalid access mode"))
             }
         }
     }
@@ -236,12 +236,18 @@ impl OpenOptions {
             (true, false) => {}
             (false, false) => {
                 if self.truncate || self.create || self.create_new {
-                    return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode"));
+                    return Err(io::Error::new_const(
+                        ErrorKind::InvalidInput,
+                        &"invalid creation mode",
+                    ));
                 }
             }
             (_, true) => {
                 if self.truncate && !self.create_new {
-                    return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode"));
+                    return Err(io::Error::new_const(
+                        ErrorKind::InvalidInput,
+                        &"invalid creation mode",
+                    ));
                 }
             }
         }
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 17a51abeb0e..1ecda25c03d 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -55,7 +55,10 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
 }
 
 pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on HermitCore yet")
+    crate::io::Error::new_const(
+        crate::io::ErrorKind::Other,
+        &"operation not supported on HermitCore yet",
+    )
 }
 
 // This enum is used as the storage for a bunch of types which can't actually
diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs
index 8a788a9265f..7053487ccfb 100644
--- a/library/std/src/sys/hermit/net.rs
+++ b/library/std/src/sys/hermit/net.rs
@@ -14,7 +14,10 @@ use crate::time::Duration;
 /// if not, starts it.
 pub fn init() -> io::Result<()> {
     if abi::network_init() < 0 {
-        return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface"));
+        return Err(io::Error::new_const(
+            ErrorKind::Other,
+            &"Unable to initialize network interface",
+        ));
     }
 
     Ok(())
@@ -47,9 +50,10 @@ impl TcpStream {
 
         match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
-            _ => {
-                Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
-            }
+            _ => Err(io::Error::new_const(
+                ErrorKind::Other,
+                &"Unable to initiate a connection on a socket",
+            )),
         }
     }
 
@@ -60,15 +64,16 @@ impl TcpStream {
             Some(duration.as_millis() as u64),
         ) {
             Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
-            _ => {
-                Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
-            }
+            _ => Err(io::Error::new_const(
+                ErrorKind::Other,
+                &"Unable to initiate a connection on a socket",
+            )),
         }
     }
 
     pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
         abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
-            .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value"))
     }
 
     pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
@@ -76,26 +81,28 @@ impl TcpStream {
             *self.0.as_inner(),
             duration.map(|d| d.as_millis() as u64),
         )
-        .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
+        .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
+        let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| {
+            io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value")
+        })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
+        let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| {
+            io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value")
+        })?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         abi::tcpstream::peek(*self.0.as_inner(), buf)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed"))
     }
 
     pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> {
@@ -107,7 +114,7 @@ impl TcpStream {
 
         for i in ioslice.iter_mut() {
             let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
-                .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
+                .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?;
 
             if ret != 0 {
                 size += ret;
@@ -130,8 +137,9 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter() {
-            size += abi::tcpstream::write(*self.0.as_inner(), i)
-                .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?;
+            size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| {
+                io::Error::new_const(ErrorKind::Other, &"Unable to write on socket")
+            })?;
         }
 
         Ok(size)
@@ -144,13 +152,13 @@ impl TcpStream {
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?;
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?;
 
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new(ErrorKind::Other, "peer_addr failed"));
+                return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed"));
             }
         };
 
@@ -158,12 +166,12 @@ impl TcpStream {
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"socket_addr isn't supported"))
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket"))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
@@ -172,31 +180,31 @@ impl TcpStream {
 
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed"))
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
         abi::tcpstream::nodelay(*self.0.as_inner())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed"))
     }
 
     pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
         abi::tcpstream::set_tll(*self.0.as_inner(), tll)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
         abi::tcpstream::get_tll(*self.0.as_inner())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL"))
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        Err(io::Error::new(ErrorKind::Other, "take_error isn't supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"take_error isn't supported"))
     }
 
     pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode"))
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode"))
     }
 }
 
@@ -222,12 +230,12 @@ impl TcpListener {
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
         let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
-            .map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?;
+            .map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?;
         let saddr = match ipaddr {
             Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
             Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
             _ => {
-                return Err(io::Error::new(ErrorKind::Other, "accept failed"));
+                return Err(io::Error::new_const(ErrorKind::Other, &"accept failed"));
             }
         };
 
@@ -239,27 +247,27 @@ impl TcpListener {
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn only_v6(&self) -> io::Result<bool> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 }
 
@@ -273,127 +281,127 @@ pub struct UdpSocket(abi::Handle);
 
 impl UdpSocket {
     pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn broadcast(&self) -> io::Result<bool> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 
     pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
     }
 }
 
diff --git a/library/std/src/sys/hermit/stdio.rs b/library/std/src/sys/hermit/stdio.rs
index 82304dd6dc2..6bff13ca92c 100644
--- a/library/std/src/sys/hermit/stdio.rs
+++ b/library/std/src/sys/hermit/stdio.rs
@@ -40,7 +40,7 @@ impl io::Write for Stdout {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -52,7 +52,7 @@ impl io::Write for Stdout {
         unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -81,7 +81,7 @@ impl io::Write for Stderr {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
@@ -93,7 +93,7 @@ impl io::Write for Stderr {
         unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) }
 
         if len < 0 {
-            Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print"))
+            Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print"))
         } else {
             Ok(len as usize)
         }
diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs
index 7bd71e120de..f35a3a8a80f 100644
--- a/library/std/src/sys/hermit/thread.rs
+++ b/library/std/src/sys/hermit/thread.rs
@@ -37,7 +37,7 @@ impl Thread {
             // The thread failed to start and as a result p was not consumed. Therefore, it is
             // safe to reconstruct the box so that it gets deallocated.
             drop(Box::from_raw(p));
-            Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!"))
+            Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!"))
         } else {
             Ok(Thread { tid: tid })
         };
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index b10bed621db..3cd245f40d9 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -50,7 +50,7 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
 }
 
 pub fn unsupported_err() -> crate::io::Error {
-    crate::io::Error::new(ErrorKind::Other, "operation not supported on SGX yet")
+    crate::io::Error::new_const(ErrorKind::Other, &"operation not supported on SGX yet")
 }
 
 /// This function is used to implement various functions that doesn't exist,
@@ -61,9 +61,9 @@ pub fn unsupported_err() -> crate::io::Error {
 pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
     static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
     if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
-        Err(crate::io::Error::new(
+        Err(crate::io::Error::new_const(
             ErrorKind::Other,
-            "operation can't be trusted to have any effect on SGX",
+            &"operation can't be trusted to have any effect on SGX",
         ))
     } else {
         Ok(v)
diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs
index 3dd8267921e..c0c5d55548c 100644
--- a/library/std/src/sys/sgx/net.rs
+++ b/library/std/src/sys/sgx/net.rs
@@ -97,9 +97,9 @@ impl TcpStream {
 
     pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
         if dur == Duration::default() {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "cannot set a 0 duration timeout",
+                &"cannot set a 0 duration timeout",
             ));
         }
         Self::connect(Ok(addr)) // FIXME: ignoring timeout
@@ -108,9 +108,9 @@ impl TcpStream {
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         match dur {
             Some(dur) if dur == Duration::default() => {
-                return Err(io::Error::new(
+                return Err(io::Error::new_const(
                     io::ErrorKind::InvalidInput,
-                    "cannot set a 0 duration timeout",
+                    &"cannot set a 0 duration timeout",
                 ));
             }
             _ => sgx_ineffective(()),
@@ -120,9 +120,9 @@ impl TcpStream {
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         match dur {
             Some(dur) if dur == Duration::default() => {
-                return Err(io::Error::new(
+                return Err(io::Error::new_const(
                     io::ErrorKind::InvalidInput,
-                    "cannot set a 0 duration timeout",
+                    &"cannot set a 0 duration timeout",
                 ));
             }
             _ => sgx_ineffective(()),
diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs
index ea05ee3d7ce..cf6aa31b7cf 100644
--- a/library/std/src/sys/unix/android.rs
+++ b/library/std/src/sys/unix/android.rs
@@ -96,7 +96,7 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
             Some(f) => cvt_r(|| f(fd, size as i64)).map(drop),
             None => {
                 if size > i32::MAX as u64 {
-                    Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot truncate >2GB"))
+                    Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB"))
                 } else {
                     cvt_r(|| ftruncate(fd, size as i32)).map(drop)
                 }
@@ -123,7 +123,7 @@ pub unsafe fn cvt_pread64(
         if let Ok(o) = offset.try_into() {
             cvt(pread(fd, buf, count, o))
         } else {
-            Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pread >2GB"))
+            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB"))
         }
     })
 }
@@ -141,7 +141,7 @@ pub unsafe fn cvt_pwrite64(
         if let Ok(o) = offset.try_into() {
             cvt(pwrite(fd, buf, count, o))
         } else {
-            Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pwrite >2GB"))
+            Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB"))
         }
     })
 }
diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs
index 21bdfe29578..9a982a4acd9 100644
--- a/library/std/src/sys/unix/ext/fs.rs
+++ b/library/std/src/sys/unix/ext/fs.rs
@@ -109,7 +109,7 @@ pub trait FileExt {
             }
         }
         if !buf.is_empty() {
-            Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+            Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
         } else {
             Ok(())
         }
@@ -191,9 +191,9 @@ pub trait FileExt {
         while !buf.is_empty() {
             match self.write_at(buf, offset) {
                 Ok(0) => {
-                    return Err(io::Error::new(
+                    return Err(io::Error::new_const(
                         io::ErrorKind::WriteZero,
-                        "failed to write whole buffer",
+                        &"failed to write whole buffer",
                     ));
                 }
                 Ok(n) => {
diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs
index 1f9036242eb..6e7d1f1678a 100644
--- a/library/std/src/sys/unix/ext/net/addr.rs
+++ b/library/std/src/sys/unix/ext/net/addr.rs
@@ -29,16 +29,16 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un,
     let bytes = path.as_os_str().as_bytes();
 
     if bytes.contains(&0) {
-        return Err(io::Error::new(
+        return Err(io::Error::new_const(
             io::ErrorKind::InvalidInput,
-            "paths may not contain interior null bytes",
+            &"paths may not contain interior null bytes",
         ));
     }
 
     if bytes.len() >= addr.sun_path.len() {
-        return Err(io::Error::new(
+        return Err(io::Error::new_const(
             io::ErrorKind::InvalidInput,
-            "path must be shorter than SUN_LEN",
+            &"path must be shorter than SUN_LEN",
         ));
     }
     for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
@@ -118,9 +118,9 @@ impl SocketAddr {
             // linux returns zero bytes of address
             len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
         } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "file descriptor did not correspond to a Unix socket",
+                &"file descriptor did not correspond to a Unix socket",
             ));
         }
 
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index d1b0ad9e5f8..f25a6280cd0 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -357,17 +357,17 @@ impl FileAttr {
                         tv_nsec: ext.stx_btime.tv_nsec as _,
                     }))
                 } else {
-                    Err(io::Error::new(
+                    Err(io::Error::new_const(
                         io::ErrorKind::Other,
-                        "creation time is not available for the filesystem",
+                        &"creation time is not available for the filesystem",
                     ))
                 };
             }
         }
 
-        Err(io::Error::new(
+        Err(io::Error::new_const(
             io::ErrorKind::Other,
-            "creation time is not available on this platform \
+            &"creation time is not available on this platform \
                             currently",
         ))
     }
@@ -1156,9 +1156,9 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)>
     let reader = File::open(from)?;
     let metadata = reader.metadata()?;
     if !metadata.is_file() {
-        return Err(Error::new(
+        return Err(Error::new_const(
             ErrorKind::InvalidInput,
-            "the source path is not an existing regular file",
+            &"the source path is not an existing regular file",
         ));
     }
     Ok((reader, metadata))
diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs
index a2912387108..d60a4b5591f 100644
--- a/library/std/src/sys/unix/l4re.rs
+++ b/library/std/src/sys/unix/l4re.rs
@@ -1,6 +1,6 @@
 macro_rules! unimpl {
     () => {
-        return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re."));
+        return Err(io::Error::new_const(io::ErrorKind::Other, &"No networking available on L4Re."));
     };
 }
 
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 587ffe15981..e6b61062d15 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -139,9 +139,9 @@ impl Socket {
         let mut pollfd = libc::pollfd { fd: self.0.raw(), events: libc::POLLOUT, revents: 0 };
 
         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "cannot set a 0 duration timeout",
+                &"cannot set a 0 duration timeout",
             ));
         }
 
@@ -150,7 +150,7 @@ impl Socket {
         loop {
             let elapsed = start.elapsed();
             if elapsed >= timeout {
-                return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out"));
+                return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out"));
             }
 
             let timeout = timeout - elapsed;
@@ -177,7 +177,10 @@ impl Socket {
                     // for POLLHUP rather than read readiness
                     if pollfd.revents & libc::POLLHUP != 0 {
                         let e = self.take_error()?.unwrap_or_else(|| {
-                            io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
+                            io::Error::new_const(
+                                io::ErrorKind::Other,
+                                &"no error set after POLLHUP",
+                            )
                         });
                         return Err(e);
                     }
@@ -318,9 +321,9 @@ impl Socket {
         let timeout = match dur {
             Some(dur) => {
                 if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
-                    return Err(io::Error::new(
+                    return Err(io::Error::new_const(
                         io::ErrorKind::InvalidInput,
-                        "cannot set a 0 duration timeout",
+                        &"cannot set a 0 duration timeout",
                     ));
                 }
 
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 1d1118aa694..4a077e2151e 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -287,9 +287,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
                 0,
             ))?;
             if path_len <= 1 {
-                return Err(io::Error::new(
+                return Err(io::Error::new_const(
                     io::ErrorKind::Other,
-                    "KERN_PROC_PATHNAME sysctl returned zero-length string",
+                    &"KERN_PROC_PATHNAME sysctl returned zero-length string",
                 ));
             }
             let mut path: Vec<u8> = Vec::with_capacity(path_len);
@@ -310,9 +310,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
         if curproc_exe.is_file() {
             return crate::fs::read_link(curproc_exe);
         }
-        Err(io::Error::new(
+        Err(io::Error::new_const(
             io::ErrorKind::Other,
-            "/proc/curproc/exe doesn't point to regular file.",
+            &"/proc/curproc/exe doesn't point to regular file.",
         ))
     }
     sysctl().or_else(|_| procfs())
@@ -329,7 +329,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
         cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?;
         argv.set_len(argv_len as usize);
         if argv[0].is_null() {
-            return Err(io::Error::new(io::ErrorKind::Other, "no current exe available"));
+            return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available"));
         }
         let argv0 = CStr::from_ptr(argv[0]).to_bytes();
         if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') {
@@ -343,9 +343,9 @@ pub fn current_exe() -> io::Result<PathBuf> {
 #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     match crate::fs::read_link("/proc/self/exe") {
-        Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new(
+        Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const(
             io::ErrorKind::Other,
-            "no /proc/self/exe available. Is /proc mounted?",
+            &"no /proc/self/exe available. Is /proc mounted?",
         )),
         other => other,
     }
@@ -431,7 +431,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
             _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::<image_info>() as i32);
         if result != 0 {
             use crate::io::ErrorKind;
-            Err(io::Error::new(ErrorKind::Other, "Error getting executable path"))
+            Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path"))
         } else {
             let name = CStr::from_ptr(info.name.as_ptr()).to_bytes();
             Ok(PathBuf::from(OsStr::from_bytes(name)))
@@ -447,7 +447,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 #[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use crate::io::ErrorKind;
-    Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
+    Err(io::Error::new_const(ErrorKind::Other, &"Not yet implemented!"))
 }
 
 #[cfg(target_os = "vxworks")]
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index 0d4703d7f50..b19ad4ccdc7 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -22,9 +22,9 @@ impl Command {
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "nul byte found in provided data",
+                &"nul byte found in provided data",
             ));
         }
 
@@ -37,7 +37,10 @@ impl Command {
 
     pub fn exec(&mut self, default: Stdio) -> io::Error {
         if self.saw_nul() {
-            return io::Error::new(io::ErrorKind::InvalidInput, "nul byte found in provided data");
+            return io::Error::new_const(
+                io::ErrorKind::InvalidInput,
+                &"nul byte found in provided data",
+            );
         }
 
         match self.setup_io(default, true) {
@@ -182,9 +185,9 @@ impl Process {
             ))?;
         }
         if actual != 1 {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidData,
-                "Failed to get exit status of process",
+                &"Failed to get exit status of process",
             ));
         }
         Ok(ExitStatus(proc_info.return_code))
@@ -220,9 +223,9 @@ impl Process {
             ))?;
         }
         if actual != 1 {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidData,
-                "Failed to get exit status of process",
+                &"Failed to get exit status of process",
             ));
         }
         Ok(Some(ExitStatus(proc_info.return_code)))
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 47aaca82af9..01f1318fe80 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -28,7 +28,10 @@ impl Command {
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"));
+            return Err(io::Error::new_const(
+                ErrorKind::InvalidInput,
+                &"nul byte found in provided data",
+            ));
         }
 
         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
@@ -118,7 +121,10 @@ impl Command {
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data");
+            return io::Error::new_const(
+                ErrorKind::InvalidInput,
+                &"nul byte found in provided data",
+            );
         }
 
         match self.setup_io(default, true) {
@@ -442,9 +448,9 @@ impl Process {
         // and used for another process, and we probably shouldn't be killing
         // random processes, so just return an error.
         if self.status.is_some() {
-            Err(Error::new(
+            Err(Error::new_const(
                 ErrorKind::InvalidInput,
-                "invalid argument: can't kill an exited process",
+                &"invalid argument: can't kill an exited process",
             ))
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs
index 2cdd9c4d19e..01e4fd3c994 100644
--- a/library/std/src/sys/unsupported/common.rs
+++ b/library/std/src/sys/unsupported/common.rs
@@ -18,7 +18,7 @@ pub fn unsupported<T>() -> std_io::Result<T> {
 }
 
 pub fn unsupported_err() -> std_io::Error {
-    std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform")
+    std_io::Error::new_const(std_io::ErrorKind::Other, &"operation not supported on this platform")
 }
 
 pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs
index 0615780c242..897927e7b79 100644
--- a/library/std/src/sys/unsupported/os.rs
+++ b/library/std/src/sys/unsupported/os.rs
@@ -80,11 +80,11 @@ pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
 }
 
 pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform"))
+    Err(io::Error::new_const(io::ErrorKind::Other, &"cannot set env vars on this platform"))
 }
 
 pub fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform"))
+    Err(io::Error::new_const(io::ErrorKind::Other, &"cannot unset env vars on this platform"))
 }
 
 pub fn temp_dir() -> PathBuf {
diff --git a/library/std/src/sys/vxworks/process/process_vxworks.rs b/library/std/src/sys/vxworks/process/process_vxworks.rs
index 69adbcdddc9..295452327eb 100644
--- a/library/std/src/sys/vxworks/process/process_vxworks.rs
+++ b/library/std/src/sys/vxworks/process/process_vxworks.rs
@@ -22,7 +22,10 @@ impl Command {
         let envp = self.capture_env();
 
         if self.saw_nul() {
-            return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"));
+            return Err(io::Error::new_const(
+                ErrorKind::InvalidInput,
+                &"nul byte found in provided data",
+            ));
         }
         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
         let mut p = Process { pid: 0, status: None };
@@ -134,9 +137,9 @@ impl Process {
         // and used for another process, and we probably shouldn't be killing
         // random processes, so just return an error.
         if self.status.is_some() {
-            Err(Error::new(
+            Err(Error::new_const(
                 ErrorKind::InvalidInput,
-                "invalid argument: can't kill an exited process",
+                &"invalid argument: can't kill an exited process",
             ))
         } else {
             cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs
index 6472642f034..ba4057bd34c 100644
--- a/library/std/src/sys/wasi/ext/fs.rs
+++ b/library/std/src/sys/wasi/ext/fs.rs
@@ -85,7 +85,7 @@ pub trait FileExt {
             }
         }
         if !buf.is_empty() {
-            Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
+            Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer"))
         } else {
             Ok(())
         }
@@ -151,9 +151,9 @@ pub trait FileExt {
         while !buf.is_empty() {
             match self.write_at(buf, offset) {
                 Ok(0) => {
-                    return Err(io::Error::new(
+                    return Err(io::Error::new_const(
                         io::ErrorKind::WriteZero,
-                        "failed to write whole buffer",
+                        &"failed to write whole buffer",
                     ));
                 }
                 Ok(n) => {
@@ -532,5 +532,5 @@ pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) ->
 }
 
 fn osstr2str(f: &OsStr) -> io::Result<&str> {
-    f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
+    f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8"))
 }
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 63c22136273..1ec3ff6a10f 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -670,7 +670,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
 }
 
 pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
-    f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
+    f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8"))
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 307a47678c6..c6509db80c0 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -513,9 +513,9 @@ impl File {
                     )
                 }
                 _ => {
-                    return Err(io::Error::new(
+                    return Err(io::Error::new_const(
                         io::ErrorKind::Other,
-                        "Unsupported reparse point type",
+                        &"Unsupported reparse point type",
                     ));
                 }
             };
@@ -802,7 +802,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
 
 #[cfg(target_vendor = "uwp")]
 pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
-    return Err(io::Error::new(io::ErrorKind::Other, "hard link are not supported on UWP"));
+    return Err(io::Error::new_const(io::ErrorKind::Other, &"hard link are not supported on UWP"));
 }
 
 pub fn stat(path: &Path) -> io::Result<FileAttr> {
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index fcbff59dec0..0353c9811f1 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -130,9 +130,9 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
     fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
         let mut maybe_result: Vec<u16> = s.encode_wide().collect();
         if unrolled_find_u16s(0, &maybe_result).is_some() {
-            return Err(crate::io::Error::new(
+            return Err(crate::io::Error::new_const(
                 ErrorKind::InvalidInput,
-                "strings passed to WinAPI cannot contain NULs",
+                &"strings passed to WinAPI cannot contain NULs",
             ));
         }
         maybe_result.push(0);
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index 9e74454bc23..e50adcb28a4 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -136,9 +136,9 @@ impl Socket {
         }
 
         if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "cannot set a 0 duration timeout",
+                &"cannot set a 0 duration timeout",
             ));
         }
 
@@ -164,7 +164,7 @@ impl Socket {
             unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? };
 
         match n {
-            0 => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")),
+            0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")),
             _ => {
                 if writefds.fd_count != 1 {
                     if let Some(e) = self.take_error()? {
@@ -339,9 +339,9 @@ impl Socket {
             Some(dur) => {
                 let timeout = sys::dur2timeout(dur);
                 if timeout == 0 {
-                    return Err(io::Error::new(
+                    return Err(io::Error::new_const(
                         io::ErrorKind::InvalidInput,
-                        "cannot set a 0 duration timeout",
+                        &"cannot set a 0 duration timeout",
                     ));
                 }
                 timeout
@@ -370,7 +370,7 @@ impl Socket {
 
     #[cfg(target_vendor = "uwp")]
     fn set_no_inherit(&self) -> io::Result<()> {
-        Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP"))
+        Err(io::Error::new_const(io::ErrorKind::Other, &"Unavailable on UWP"))
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 83d37795ee5..30bbfdd0dd1 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -62,7 +62,7 @@ impl AsRef<OsStr> for EnvKey {
 
 fn ensure_no_nuls<T: AsRef<OsStr>>(str: T) -> io::Result<T> {
     if str.as_ref().encode_wide().any(|b| b == 0) {
-        Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"))
+        Err(io::Error::new_const(ErrorKind::InvalidInput, &"nul byte found in provided data"))
     } else {
         Ok(str)
     }
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index ff214497166..be3141e46a1 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -68,9 +68,9 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
     let utf8 = match str::from_utf8(&data[..len]) {
         Ok(s) => s,
         Err(ref e) if e.valid_up_to() == 0 => {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidData,
-                "Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
             ));
         }
         Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
@@ -149,9 +149,9 @@ impl io::Read for Stdin {
         if buf.len() == 0 {
             return Ok(0);
         } else if buf.len() < 4 {
-            return Err(io::Error::new(
+            return Err(io::Error::new_const(
                 io::ErrorKind::InvalidInput,
-                "Windows stdin in console mode does not support a buffer too small to \
+                &"Windows stdin in console mode does not support a buffer too small to \
                  guarantee holding one arbitrary UTF-8 character (4 bytes)",
             ));
         }
@@ -243,9 +243,9 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
             }
             Err(_) => {
                 // We can't really do any better than forget all data and return an error.
-                return Err(io::Error::new(
+                return Err(io::Error::new_const(
                     io::ErrorKind::InvalidData,
-                    "Windows stdin in console mode does not support non-UTF-16 input; \
+                    &"Windows stdin in console mode does not support non-UTF-16 input; \
                      encountered unpaired surrogate",
                 ));
             }
diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs
index 6bdb26cd078..92d0cc60850 100644
--- a/library/std/src/sys_common/fs.rs
+++ b/library/std/src/sys_common/fs.rs
@@ -9,9 +9,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     let metadata = reader.metadata()?;
 
     if !metadata.is_file() {
-        return Err(Error::new(
+        return Err(Error::new_const(
             ErrorKind::InvalidInput,
-            "the source path is not an existing regular file",
+            &"the source path is not an existing regular file",
         ));
     }
 
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 38ba0d2fbdb..d5f29c4a439 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -108,7 +108,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result
                 *(storage as *const _ as *const c::sockaddr_in6)
             })))
         }
-        _ => Err(Error::new(ErrorKind::InvalidInput, "invalid argument")),
+        _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")),
     }
 }
 
@@ -171,7 +171,7 @@ impl TryFrom<&str> for LookupHost {
             ($e:expr, $msg:expr) => {
                 match $e {
                     Some(r) => r,
-                    None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)),
+                    None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)),
                 }
             };
         }
diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs
index 64a5f89890a..e8cdde88014 100644
--- a/library/std/src/thread/available_concurrency.rs
+++ b/library/std/src/thread/available_concurrency.rs
@@ -64,7 +64,7 @@ cfg_if::cfg_if! {
                 sysinfo.dwNumberOfProcessors as usize
             };
             match res {
-                0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")),
+                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
                 cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }),
             }
         }
@@ -81,7 +81,7 @@ cfg_if::cfg_if! {
         fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
             match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
                 -1 => Err(io::Error::last_os_error()),
-                0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")),
+                0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
                 cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }),
             }
         }
@@ -114,7 +114,7 @@ cfg_if::cfg_if! {
                 if res == -1 {
                     return Err(io::Error::last_os_error());
                 } else if cpus == 0 {
-                    return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
+                    return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
                 }
             }
             Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
@@ -142,7 +142,7 @@ cfg_if::cfg_if! {
             if res == -1 {
                 return Err(io::Error::last_os_error());
             } else if cpus == 0 {
-                return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
+                return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"));
             }
 
             Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
@@ -150,7 +150,7 @@ cfg_if::cfg_if! {
     } else {
         // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re
         fn available_concurrency_internal() -> io::Result<NonZeroUsize> {
-            Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"))
+            Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform"))
         }
     }
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e5fe1159928..84210276d35 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -231,7 +231,7 @@ impl Clean<Item> for doctree::Module<'_> {
 
         let what_rustc_thinks = Item::from_hir_id_and_parts(
             self.id,
-            self.name,
+            Some(self.name),
             ModuleItem(Module { is_crate: self.is_crate, items }),
             cx,
         );
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3dd27933471..142121b7346 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -51,7 +51,7 @@ thread_local!(crate static MAX_DEF_IDX: RefCell<FxHashMap<CrateNum, DefIndex>> =
 crate struct Crate {
     crate name: Symbol,
     crate src: FileName,
-    crate module: Option<Item>,
+    crate module: Item,
     crate externs: Vec<(CrateNum, ExternalCrate)>,
     crate primitives: Vec<(DefId, PrimitiveType)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 6f283d501a4..582cbf69ed1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -76,7 +76,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     Crate {
         name,
         src,
-        module: Some(module),
+        module,
         externs,
         primitives,
         external_traits: cx.external_traits.clone(),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c5b5ab0f3d0..5a022b2d40c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -474,21 +474,19 @@ crate fn run_global_ctxt(
 
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
-    if let Some(ref m) = krate.module {
-        if m.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
-            let help = "The following guide may be of use:\n\
+    if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
+        let help = "The following guide may be of use:\n\
                 https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
-            tcx.struct_lint_node(
-                crate::lint::MISSING_CRATE_LEVEL_DOCS,
-                DocContext::as_local_hir_id(tcx, m.def_id).unwrap(),
-                |lint| {
-                    let mut diag =
-                        lint.build("no documentation found for this crate's top-level module");
-                    diag.help(help);
-                    diag.emit();
-                },
-            );
-        }
+        tcx.struct_lint_node(
+            crate::lint::MISSING_CRATE_LEVEL_DOCS,
+            DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
+            |lint| {
+                let mut diag =
+                    lint.build("no documentation found for this crate's top-level module");
+                diag.help(help);
+                diag.emit();
+            },
+        );
     }
 
     fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
@@ -531,7 +529,7 @@ crate fn run_global_ctxt(
 
     // Process all of the crate attributes, extracting plugin metadata along
     // with the passes which we are supposed to run.
-    for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) {
+    for attr in krate.module.attrs.lists(sym::doc) {
         let diag = ctxt.sess().diagnostic();
 
         let name = attr.name_or_empty();
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 645b2bb193e..189624c0d80 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -5,7 +5,7 @@ use rustc_span::{self, Span, Symbol};
 use rustc_hir as hir;
 
 crate struct Module<'hir> {
-    crate name: Option<Symbol>,
+    crate name: Symbol,
     crate where_outer: Span,
     crate where_inner: Span,
     crate mods: Vec<Module<'hir>>,
@@ -18,7 +18,7 @@ crate struct Module<'hir> {
 }
 
 impl Module<'hir> {
-    crate fn new(name: Option<Symbol>) -> Module<'hir> {
+    crate fn new(name: Symbol) -> Module<'hir> {
         Module {
             name,
             id: hir::CRATE_HIR_ID,
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 2b980ebe592..376fef6568a 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -87,7 +87,7 @@ crate trait DocFolder: Sized {
     }
 
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
-        c.module = c.module.take().and_then(|module| self.fold_item(module));
+        c.module = self.fold_item(c.module).unwrap();
 
         {
             let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 9415caf8b6f..f9a663b38eb 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -182,8 +182,6 @@ impl Cache {
             self.primitive_locations.insert(prim, def_id);
         }
 
-        self.stack.push(krate.name.to_string());
-
         krate = CacheBuilder { tcx, cache: self, empty_cache: Cache::default() }.fold_crate(krate);
 
         for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) {
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 9095faf6761..9dcef3a20d6 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -1,5 +1,5 @@
 use rustc_middle::ty::TyCtxt;
-use rustc_span::edition::Edition;
+use rustc_span::{edition::Edition, Symbol};
 
 use crate::clean;
 use crate::config::RenderOptions;
@@ -40,7 +40,7 @@ crate trait FormatRenderer<'tcx>: Sized {
     /// A handler is available if the renderer wants to report errors.
     fn after_krate(
         &mut self,
-        krate: &clean::Crate,
+        crate_name: Symbol,
         diag: &rustc_errors::Handler,
     ) -> Result<(), Error>;
 
@@ -58,21 +58,15 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
 ) -> Result<(), Error> {
     let prof = &tcx.sess.prof;
 
-    let (mut format_renderer, mut krate) = prof
+    let (mut format_renderer, krate) = prof
         .extra_verbose_generic_activity("create_renderer", T::descr())
         .run(|| T::init(krate, options, edition, cache, tcx))?;
 
-    let mut item = match krate.module.take() {
-        Some(i) => i,
-        None => return Ok(()),
-    };
-
-    item.name = Some(krate.name);
-
     // Render the crate documentation
-    let mut work = vec![(format_renderer.make_child_renderer(), item)];
+    let crate_name = krate.name;
+    let mut work = vec![(format_renderer.make_child_renderer(), krate.module)];
 
-    let unknown = rustc_span::Symbol::intern("<unknown item>");
+    let unknown = Symbol::intern("<unknown item>");
     while let Some((mut cx, item)) = work.pop() {
         if item.is_mod() {
             // modules are special because they add a namespace. We also need to
@@ -102,5 +96,5 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
         }
     }
     prof.extra_verbose_generic_activity("renderer_after_krate", T::descr())
-        .run(|| format_renderer.after_krate(&krate, diag))
+        .run(|| format_renderer.after_krate(crate_name, diag))
 }
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 56fee2c9fec..5d49a494727 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -127,11 +127,8 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
         crate_items.push(&*item);
     }
 
-    let crate_doc = krate
-        .module
-        .as_ref()
-        .map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
-        .unwrap_or_default();
+    let crate_doc =
+        krate.module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s));
 
     struct CrateData<'a> {
         doc: String,
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 05993d8df60..64d413a5f31 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::FileName;
-use rustc_span::symbol::sym;
+use rustc_span::{symbol::sym, Symbol};
 
 use super::cache::{build_index, ExternalLocation};
 use super::print_item::{full_path, item_path, print_item};
@@ -343,29 +343,27 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
         // Crawl the crate attributes looking for attributes which control how we're
         // going to emit HTML
-        if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
-            for attr in attrs.lists(sym::doc) {
-                match (attr.name_or_empty(), attr.value_str()) {
-                    (sym::html_favicon_url, Some(s)) => {
-                        layout.favicon = s.to_string();
-                    }
-                    (sym::html_logo_url, Some(s)) => {
-                        layout.logo = s.to_string();
-                    }
-                    (sym::html_playground_url, Some(s)) => {
-                        playground = Some(markdown::Playground {
-                            crate_name: Some(krate.name.to_string()),
-                            url: s.to_string(),
-                        });
-                    }
-                    (sym::issue_tracker_base_url, Some(s)) => {
-                        issue_tracker_base_url = Some(s.to_string());
-                    }
-                    (sym::html_no_source, None) if attr.is_word() => {
-                        include_sources = false;
-                    }
-                    _ => {}
+        for attr in krate.module.attrs.lists(sym::doc) {
+            match (attr.name_or_empty(), attr.value_str()) {
+                (sym::html_favicon_url, Some(s)) => {
+                    layout.favicon = s.to_string();
+                }
+                (sym::html_logo_url, Some(s)) => {
+                    layout.logo = s.to_string();
+                }
+                (sym::html_playground_url, Some(s)) => {
+                    playground = Some(markdown::Playground {
+                        crate_name: Some(krate.name.to_string()),
+                        url: s.to_string(),
+                    });
+                }
+                (sym::issue_tracker_base_url, Some(s)) => {
+                    issue_tracker_base_url = Some(s.to_string());
+                }
+                (sym::html_no_source, None) if attr.is_word() => {
+                    include_sources = false;
                 }
+                _ => {}
             }
         }
         let (sender, receiver) = channel();
@@ -447,12 +445,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
     fn after_krate(
         &mut self,
-        krate: &clean::Crate,
+        crate_name: Symbol,
         diag: &rustc_errors::Handler,
     ) -> Result<(), Error> {
-        let final_file = self.dst.join(&*krate.name.as_str()).join("all.html");
+        let final_file = self.dst.join(&*crate_name.as_str()).join("all.html");
         let settings_file = self.dst.join("settings.html");
-        let crate_name = krate.name;
 
         let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
         if !root_path.ends_with('/') {
@@ -515,9 +512,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if let Some(ref redirections) = self.shared.redirections {
             if !redirections.borrow().is_empty() {
                 let redirect_map_path =
-                    self.dst.join(&*krate.name.as_str()).join("redirect-map.json");
+                    self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
                 let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
-                self.shared.ensure_dir(&self.dst.join(&*krate.name.as_str()))?;
+                self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
                 self.shared.fs.write(&redirect_map_path, paths.as_bytes())?;
             }
         }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 128eac8cb0a..05d30187aa8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2122,22 +2122,22 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
         items: &[clean::Item],
         before: &str,
         filter: impl Fn(&clean::Item) -> bool,
-        write: impl Fn(&mut Buffer, &Symbol),
+        write: impl Fn(&mut Buffer, &str),
         after: &str,
     ) {
         let mut items = items
             .iter()
             .filter_map(|m| match m.name {
-                Some(ref name) if filter(m) => Some(name),
+                Some(ref name) if filter(m) => Some(name.as_str()),
                 _ => None,
             })
             .collect::<Vec<_>>();
 
         if !items.is_empty() {
-            items.sort();
+            items.sort_unstable();
             out.push_str(before);
             for item in items.into_iter() {
-                write(out, item);
+                write(out, &item);
             }
             out.push_str(after);
         }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index a65b4ce3a03..6c90fd7c9ee 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -858,6 +858,15 @@ body.blur > :not(#help) {
 	font-size: 1.5em;
 }
 
+/* Black one-pixel outline around emoji shapes */
+.emoji {
+	text-shadow:
+		1px 0 0 black,
+		-1px 0 0 black,
+		0  1px 0 black,
+		0 -1px 0 black;
+}
+
 .module-item .stab {
 	border-radius: 3px;
 	display: inline-block;
@@ -1353,7 +1362,7 @@ h4 > .notable-traits {
 	to prevent an overlay between the "collapse toggle" and the information tooltip.
 	However, it's not needed with smaller screen width because the doc/code block is always put
 	"one line" below. */
-	.information:first-child > .tooltip {
+	.docblock > .information:first-child > .tooltip {
 		margin-top: 16px;
 	}
 }
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 88ac3252bb4..cf2d28bb43f 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -220,8 +220,8 @@ a.test-arrow {
 }
 
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
-.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
-.stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
 .stab.portability > code { background: none; }
 
 #help > div {
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 9bc21102aaa..7bf6793809c 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -218,8 +218,8 @@ a.test-arrow {
 }
 
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; }
-.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
-.stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
+.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
+.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
 .stab.portability > code { background: none; }
 
 #help > div {
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index c1dbb5dd33a..a4cdad69865 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -14,7 +14,7 @@ use std::rc::Rc;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
-use rustc_span::edition::Edition;
+use rustc_span::{edition::Edition, Symbol};
 
 use rustdoc_json_types as types;
 
@@ -202,7 +202,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
 
     fn after_krate(
         &mut self,
-        _krate: &clean::Crate,
+        _crate_name: Symbol,
         _diag: &rustc_errors::Handler,
     ) -> Result<(), Error> {
         debug!("Done with crate");
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 685451b87ed..7b0b2f28fdf 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -131,12 +131,8 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
         }
     }
 
-    let items = if let Some(ref mut it) = krate.module {
-        if let ModuleItem(Module { ref mut items, .. }) = *it.kind {
-            items
-        } else {
-            panic!("collect-trait-impls can't run");
-        }
+    let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind {
+        items
     } else {
         panic!("collect-trait-impls can't run");
     };
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index b6782fb75df..17a66d1788e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -76,7 +76,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             &krate.item.module,
-            None,
+            self.cx.tcx.crate_name,
         );
         top_level_module.is_crate = true;
         // Attach the crate's exported macros to the top-level module.
@@ -114,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     _ => continue 'exported_macros,
                 };
                 // Descend into the child module that matches this path segment (if any).
-                match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) {
+                match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) {
                     Some(child_mod) => cur_mod = &mut *child_mod,
                     None => continue 'exported_macros,
                 }
@@ -133,7 +133,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         vis: &'tcx hir::Visibility<'_>,
         id: hir::HirId,
         m: &'tcx hir::Mod<'tcx>,
-        name: Option<Symbol>,
+        name: Symbol,
     ) -> Module<'tcx> {
         let mut om = Module::new(name);
         om.where_outer = span;
@@ -312,13 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.items.push((item, renamed))
             }
             hir::ItemKind::Mod(ref m) => {
-                om.mods.push(self.visit_mod_contents(
-                    item.span,
-                    &item.vis,
-                    item.hir_id(),
-                    m,
-                    Some(name),
-                ));
+                om.mods.push(self.visit_mod_contents(item.span, &item.vis, item.hir_id(), m, name));
             }
             hir::ItemKind::Fn(..)
             | hir::ItemKind::ExternCrate(..)
diff --git a/src/test/codegen/default-requires-uwtable.rs b/src/test/codegen/default-requires-uwtable.rs
new file mode 100644
index 00000000000..d4c4200c5d2
--- /dev/null
+++ b/src/test/codegen/default-requires-uwtable.rs
@@ -0,0 +1,15 @@
+// revisions: WINDOWS ANDROID
+// needs-llvm-components: x86 arm
+// compile-flags: -C panic=abort
+// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
+// [ANDROID] compile-flags: --target=armv7-linux-androideabi
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+// CHECK: attributes #{{.*}} uwtable
+pub fn foo() {}
diff --git a/src/test/codegen/force-no-unwind-tables.rs b/src/test/codegen/force-no-unwind-tables.rs
new file mode 100644
index 00000000000..dc77e6cb709
--- /dev/null
+++ b/src/test/codegen/force-no-unwind-tables.rs
@@ -0,0 +1,7 @@
+// compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n
+// ignore-windows
+
+#![crate_type="lib"]
+
+// CHECK-NOT: attributes #{{.*}} uwtable
+pub fn foo() {}
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index aabdaa66411..4f5f6169f36 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -3,6 +3,7 @@
 
 // revisions: cfail1 cfail2
 // build-pass (FIXME(62277): could be check-pass?)
+// compile-flags: -Z query-dep-graph
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
index 19df2972f89..1fb0f8aa84d 100644
--- a/src/test/incremental/ich_resolve_results.rs
+++ b/src/test/incremental/ich_resolve_results.rs
@@ -2,6 +2,7 @@
 // `use` to something different.
 
 // revisions: rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index 2574ef5199c..37728af9516 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -3,7 +3,7 @@
 
 // revisions:rpass1 rpass2
 
-// compile-flags: -C overflow-checks=on
+// compile-flags: -C overflow-checks=on -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml
new file mode 100644
index 00000000000..9aa72a3ad53
--- /dev/null
+++ b/src/test/rustdoc-gui/check_info_sign_position.goml
@@ -0,0 +1,9 @@
+goto: file://|DOC_PATH|/index.html
+goto: ./fn.check_list_code_block.html
+// If the codeblock is the first element of the docblock, the information tooltip must have
+// have some top margin to avoid going over the toggle (the "[+]").
+assert: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
+// Checks that the other codeblocks don't have this top margin.
+assert: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
+assert: ("ol > li > .information > .ignore", { "margin-top": "0px" })
+assert: (".docblock > .information > .ignore", { "margin-top": "0px" })
diff --git a/src/test/rustdoc-gui/lib.rs b/src/test/rustdoc-gui/lib.rs
index 15d8dcc6e84..c1e161e1235 100644
--- a/src/test/rustdoc-gui/lib.rs
+++ b/src/test/rustdoc-gui/lib.rs
@@ -47,26 +47,41 @@ pub fn some_more_function<T: fmt::Debug>(t: &T) -> String {
 
 /// Woohoo! A trait!
 pub trait AnotherOne {
+    /// Some func 3.
+    fn func3();
+
     /// Some func 1.
     fn func1();
 
+    fn another();
+    fn why_not();
+
     /// Some func 2.
     fn func2();
 
-    /// Some func 3.
-    fn func3();
+    fn hello();
 }
 
+/// ```compile_fail
+/// whatever
+/// ```
+///
 /// Check for "i" signs in lists!
 ///
 /// 1. elem 1
-/// 2.test 1
-///   ```compile_fail
-///   fn foo() {}
-///   ```
+/// 2. test 1
+///    ```compile_fail
+///    fn foo() {}
+///    ```
 /// 3. elem 3
 /// 4. ```ignore (it's a test)
 ///    fn foo() {}
 ///    ```
 /// 5. elem 5
+///
+/// Final one:
+///
+/// ```ignore (still a test)
+/// let x = 12;
+/// ```
 pub fn check_list_code_block() {}
diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml
new file mode 100644
index 00000000000..914486e1c28
--- /dev/null
+++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml
@@ -0,0 +1,7 @@
+goto: file://|DOC_PATH|/trait.AnotherOne.html
+assert: (".sidebar-links a:nth-of-type(1)", "another")
+assert: (".sidebar-links a:nth-of-type(2)", "func1")
+assert: (".sidebar-links a:nth-of-type(3)", "func2")
+assert: (".sidebar-links a:nth-of-type(4)", "func3")
+assert: (".sidebar-links a:nth-of-type(5)", "hello")
+assert: (".sidebar-links a:nth-of-type(6)", "why_not")
diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs
new file mode 100644
index 00000000000..e429e75b214
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+//! [my_module]
+//~^ WARN public documentation for `private_from_crate_level` links to private item `my_module`
+
+mod my_module {}
diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
new file mode 100644
index 00000000000..6172cd2e316
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
@@ -0,0 +1,11 @@
+warning: public documentation for `private_from_crate_level` links to private item `my_module`
+  --> $DIR/private-from-crate-level.rs:3:6
+   |
+LL | //! [my_module]
+   |      ^^^^^^^^^ this item is private
+   |
+   = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
+   = note: this link will resolve properly if you pass `--document-private-items`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.rs b/src/test/ui/dep-graph/dep-graph-check-attr.rs
new file mode 100644
index 00000000000..1026efc1b1d
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-check-attr.rs
@@ -0,0 +1,20 @@
+// Test that using rustc_clean/dirty/if_this_changed/then_this_would_need
+// are forbidden when `-Z query-dep-graph` is not enabled.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+#[rustc_dirty(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
+fn main() {}
+
+#[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
+struct Foo<T> {
+    f: T,
+}
+
+#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
+type TypeAlias<T> = Foo<T>;
+
+#[rustc_then_this_would_need(variances_of)] //~ ERROR attribute requires -Z query-dep-graph
+trait Use<T> {}
diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.stderr b/src/test/ui/dep-graph/dep-graph-check-attr.stderr
new file mode 100644
index 00000000000..945a4237c12
--- /dev/null
+++ b/src/test/ui/dep-graph/dep-graph-check-attr.stderr
@@ -0,0 +1,26 @@
+error: attribute requires -Z query-dep-graph to be enabled
+  --> $DIR/dep-graph-check-attr.rs:8:1
+   |
+LL | #[rustc_dirty(hir_owner)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute requires -Z query-dep-graph to be enabled
+  --> $DIR/dep-graph-check-attr.rs:11:1
+   |
+LL | #[rustc_if_this_changed(hir_owner)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute requires -Z query-dep-graph to be enabled
+  --> $DIR/dep-graph-check-attr.rs:16:1
+   |
+LL | #[rustc_clean(hir_owner)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute requires -Z query-dep-graph to be enabled
+  --> $DIR/dep-graph-check-attr.rs:19:1
+   |
+LL | #[rustc_then_this_would_need(variances_of)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+