diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 4c7822acdf7..02baa395c3c 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -73,34 +73,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'t
     }
 }
 
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        match self {
-            // WARNING: We dedup cache the `HashStable` results for `List`
-            // while ignoring types and freely transmute
-            // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
-            // See `fn mk_type_list` for more details.
-            //
-            // We therefore hash types without adding a hash for their discriminant.
-            //
-            // In order to make it very unlikely for the sequence of bytes being hashed for
-            // a `GenericArgKind::Type` to be the same as the sequence of bytes being
-            // hashed for one of the other variants, we hash some very high number instead
-            // of their actual discriminant since `TyKind` should never start with anything
-            // that high.
-            ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
-            ty::subst::GenericArgKind::Const(ct) => {
-                0xF3u8.hash_stable(hcx, hasher);
-                ct.hash_stable(hcx, hasher);
-            }
-            ty::subst::GenericArgKind::Lifetime(lt) => {
-                0xF5u8.hash_stable(hcx, hasher);
-                lt.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
 // AllocIds get resolved to whatever they point to (to be stable)
 impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5315aa155a8..888b3a50b77 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -738,7 +738,9 @@ pub trait PrettyPrinter<'tcx>:
                 }
             }
             ty::Placeholder(placeholder) => match placeholder.bound.kind {
-                ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
+                ty::BoundTyKind::Anon => {
+                    self.pretty_print_placeholder_var(placeholder.universe, placeholder.bound.var)?
+                }
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -1172,6 +1174,18 @@ pub trait PrettyPrinter<'tcx>:
         }
     }
 
+    fn pretty_print_placeholder_var(
+        &mut self,
+        ui: ty::UniverseIndex,
+        var: ty::BoundVar,
+    ) -> Result<(), Self::Error> {
+        if ui == ty::UniverseIndex::ROOT {
+            write!(self, "!{}", var.index())
+        } else {
+            write!(self, "!{}_{}", ui.index(), var.index())
+        }
+    }
+
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
         None
     }
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 73c9c86f76a..a439211ca33 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -47,7 +47,7 @@ const TYPE_TAG: usize = 0b00;
 const REGION_TAG: usize = 0b01;
 const CONST_TAG: usize = 0b10;
 
-#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
 pub enum GenericArgKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 7a2420a6d94..7d04aead8bc 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -507,12 +507,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             //
             // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
             &const_debuginfo::ConstDebugInfo,
-            &o1(simplify_branches::SimplifyConstConditionPassName::AfterConstProp),
+            &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
             &early_otherwise_branch::EarlyOtherwiseBranch,
             &simplify_comparison_integral::SimplifyComparisonIntegral,
             &dead_store_elimination::DeadStoreElimination,
             &dest_prop::DestinationPropagation,
-            &o1(simplify_branches::SimplifyConstConditionPassName::Final),
+            &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
             &o1(simplify::SimplifyCfg::Final),
             &nrvo::RenameReturnPlace,
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index ddaf86a9e73..c65a7ec6783 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,18 +2,16 @@ use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-pub enum SimplifyConstConditionPassName {
+pub enum SimplifyConstCondition {
     AfterConstProp,
     Final,
 }
 /// A pass that replaces a branch with a goto when its condition is known.
-impl<'tcx> MirPass<'tcx> for SimplifyConstConditionPassName {
+impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
     fn name(&self) -> &'static str {
         match self {
-            SimplifyConstConditionPassName::AfterConstProp => {
-                "SimplifyConstCondition-after-const-prop"
-            }
-            SimplifyConstConditionPassName::Final => "SimplifyConstCondition-final",
+            SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
+            SimplifyConstCondition::Final => "SimplifyConstCondition-final",
         }
     }
 
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
index ebd74012dcd..9bcd56bed00 100644
--- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
+    base.cpu = "M68020".into();
     base.max_atomic_width = Some(32);
 
     Target {
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 62e699eefd7..4c1f2dd0e53 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -203,6 +203,10 @@ pub enum TyKind<I: Interner> {
     /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables
     /// back to inference variables in a new inference context when inside of the query.
     ///
+    /// It is conventional to render anonymous bound types like `^N` or `^D_N`,
+    /// where `N` is the bound variable's anonymous index into the binder, and
+    /// `D` is the debruijn index, or totally omitted if the debruijn index is zero.
+    ///
     /// See the `rustc-dev-guide` for more details about
     /// [higher-ranked trait bounds][1] and [canonical queries][2].
     ///
@@ -212,6 +216,12 @@ pub enum TyKind<I: Interner> {
 
     /// A placeholder type, used during higher ranked subtyping to instantiate
     /// bound variables.
+    ///
+    /// It is conventional to render anonymous placeholer types like `!N` or `!U_N`,
+    /// where `N` is the placeholder variable's anonymous index (which corresponds
+    /// to the bound variable's index from the binder from which it was instantiated),
+    /// and `U` is the universe index in which it is instantiated, or totally omitted
+    /// if the universe index is zero.
     Placeholder(I::PlaceholderType),
 
     /// A type variable used during type checking.
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index ad48315fd70..f83c8f83cc9 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -7,7 +7,7 @@ use core::fmt::{self, Debug, Display, Formatter};
 use core::marker::PhantomData;
 #[cfg(not(no_global_oom_handling))]
 use core::marker::Unsize;
-use core::mem;
+use core::mem::{self, SizedTypeProperties};
 use core::ops::{Deref, DerefMut};
 use core::ptr::Pointee;
 use core::ptr::{self, NonNull};
@@ -202,9 +202,7 @@ impl<H> WithHeader<H> {
             let ptr = if layout.size() == 0 {
                 // Some paranoia checking, mostly so that the ThinBox tests are
                 // more able to catch issues.
-                debug_assert!(
-                    value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
-                );
+                debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);
                 layout.dangling()
             } else {
                 let ptr = alloc::alloc(layout);
@@ -249,9 +247,7 @@ impl<H> WithHeader<H> {
                         alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout);
                     } else {
                         debug_assert!(
-                            value_offset == 0
-                                && mem::size_of::<H>() == 0
-                                && self.value_layout.size() == 0
+                            value_offset == 0 && H::IS_ZST && self.value_layout.size() == 0
                         );
                     }
                 }
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index e3ca6eb7833..3091efabd68 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -112,9 +112,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
             let unyielded_ptr = this.iter.as_slice().as_ptr();
 
             // ZSTs have no identity, so we don't need to move them around.
-            let needs_move = mem::size_of::<T>() != 0;
-
-            if needs_move {
+            if !T::IS_ZST {
                 let start_ptr = source_vec.as_mut_ptr().add(start);
 
                 // memmove back unyielded elements
diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs
index 8c03f1692d9..650f9213890 100644
--- a/library/alloc/src/vec/drain_filter.rs
+++ b/library/alloc/src/vec/drain_filter.rs
@@ -1,5 +1,5 @@
 use crate::alloc::{Allocator, Global};
-use core::mem::{self, ManuallyDrop};
+use core::mem::{ManuallyDrop, SizedTypeProperties};
 use core::ptr;
 use core::slice;
 
@@ -96,9 +96,7 @@ where
 
         unsafe {
             // ZSTs have no identity, so we don't need to move them around.
-            let needs_move = mem::size_of::<T>() != 0;
-
-            if needs_move && this.idx < this.old_len && this.del > 0 {
+            if !T::IS_ZST && this.idx < this.old_len && this.del > 0 {
                 let ptr = this.vec.as_mut_ptr();
                 let src = ptr.add(this.idx);
                 let dst = src.sub(this.del);
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index b73e35f1e91..b1ca872b845 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -73,7 +73,7 @@ macro_rules! iterator {
             // Unsafe because the offset must not exceed `self.len()`.
             #[inline(always)]
             unsafe fn post_inc_start(&mut self, offset: usize) -> * $raw_mut T {
-                if mem::size_of::<T>() == 0 {
+                if T::IS_ZST {
                     zst_shrink!(self, offset);
                     self.ptr.as_ptr()
                 } else {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 463184acaa1..a5f08fdac11 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -32,6 +32,7 @@ mod context;
 mod print_item;
 mod sidebar;
 mod span_map;
+mod type_layout;
 mod write_shared;
 
 pub(crate) use self::context::*;
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 9a968e48b27..3e71d41ec96 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -6,16 +6,14 @@ use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::stability;
-use rustc_middle::span_bug;
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, Adt, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
 
+use super::type_layout::document_type_layout;
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
     item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
@@ -1933,118 +1931,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a
     })
 }
 
-fn document_type_layout<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    ty_def_id: DefId,
-) -> impl fmt::Display + 'a + Captures<'cx> {
-    fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
-        if layout.abi.is_unsized() {
-            write!(w, "(unsized)").unwrap();
-        } else {
-            let size = layout.size.bytes() - tag_size;
-            write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
-            if layout.abi.is_uninhabited() {
-                write!(
-                    w,
-                    " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
-                ).unwrap();
-            }
-        }
-    }
-
-    display_fn(move |mut f| {
-        if !cx.shared.show_type_layout {
-            return Ok(());
-        }
-
-        writeln!(
-            f,
-            "<h2 id=\"layout\" class=\"small-section-header\"> \
-            Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
-        )?;
-        writeln!(f, "<div class=\"docblock\">")?;
-
-        let tcx = cx.tcx();
-        let param_env = tcx.param_env(ty_def_id);
-        let ty = tcx.type_of(ty_def_id).subst_identity();
-        match tcx.layout_of(param_env.and(ty)) {
-            Ok(ty_layout) => {
-                writeln!(
-                    f,
-                    "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
-                    <strong>completely unstable</strong> and may even differ between compilations. \
-                    The only exception is types with certain <code>repr(...)</code> attributes. \
-                    Please see the Rust Reference’s \
-                    <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
-                    chapter for details on type layout guarantees.</p></div>"
-                )?;
-                f.write_str("<p><strong>Size:</strong> ")?;
-                write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
-                writeln!(f, "</p>")?;
-                if let Variants::Multiple { variants, tag, tag_encoding, .. } =
-                    &ty_layout.layout.variants()
-                {
-                    if !variants.is_empty() {
-                        f.write_str(
-                            "<p><strong>Size for each variant:</strong></p>\
-                                <ul>",
-                        )?;
-
-                        let Adt(adt, _) = ty_layout.ty.kind() else {
-                            span_bug!(tcx.def_span(ty_def_id), "not an adt")
-                        };
-
-                        let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
-                            0
-                        } else if let Primitive::Int(i, _) = tag.primitive() {
-                            i.size().bytes()
-                        } else {
-                            span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
-                        };
-
-                        for (index, layout) in variants.iter_enumerated() {
-                            let name = adt.variant(index).name;
-                            write!(&mut f, "<li><code>{name}</code>: ")?;
-                            write_size_of_layout(&mut f, layout, tag_size);
-                            writeln!(&mut f, "</li>")?;
-                        }
-                        f.write_str("</ul>")?;
-                    }
-                }
-            }
-            // This kind of layout error can occur with valid code, e.g. if you try to
-            // get the layout of a generic type such as `Vec<T>`.
-            Err(LayoutError::Unknown(_)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Unable to compute type layout, \
-                    possibly due to this type having generic parameters. \
-                    Layout can only be computed for concrete, fully-instantiated types.</p>"
-                )?;
-            }
-            // This kind of error probably can't happen with valid code, but we don't
-            // want to panic and prevent the docs from building, so we just let the
-            // user know that we couldn't compute the layout.
-            Err(LayoutError::SizeOverflow(_)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Encountered an error during type layout; \
-                    the type was too big.</p>"
-                )?;
-            }
-            Err(LayoutError::NormalizationFailure(_, _)) => {
-                writeln!(
-                    f,
-                    "<p><strong>Note:</strong> Encountered an error during type layout; \
-                    the type failed to be normalized.</p>"
-                )?;
-            }
-        }
-
-        writeln!(f, "</div>")
-    })
-}
-
 fn pluralize(count: usize) -> &'static str {
     if count > 1 { "s" } else { "" }
 }
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
new file mode 100644
index 00000000000..22aec623335
--- /dev/null
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -0,0 +1,86 @@
+use askama::Template;
+
+use rustc_data_structures::captures::Captures;
+use rustc_hir::def_id::DefId;
+use rustc_middle::span_bug;
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::Adt;
+use rustc_span::symbol::Symbol;
+use rustc_target::abi::{Primitive, TagEncoding, Variants};
+
+use std::fmt;
+
+use crate::html::format::display_fn;
+use crate::html::render::Context;
+
+#[derive(Template)]
+#[template(path = "type_layout.html")]
+struct TypeLayout<'cx> {
+    variants: Vec<(Symbol, TypeLayoutSize)>,
+    type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
+}
+
+#[derive(Template)]
+#[template(path = "type_layout_size.html")]
+struct TypeLayoutSize {
+    is_unsized: bool,
+    is_uninhabited: bool,
+    size: u64,
+}
+
+pub(crate) fn document_type_layout<'a, 'cx: 'a>(
+    cx: &'a Context<'cx>,
+    ty_def_id: DefId,
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |f| {
+        if !cx.shared.show_type_layout {
+            return Ok(());
+        }
+
+        let tcx = cx.tcx();
+        let param_env = tcx.param_env(ty_def_id);
+        let ty = tcx.type_of(ty_def_id).subst_identity();
+        let type_layout = tcx.layout_of(param_env.and(ty));
+
+        let variants =
+            if let Ok(type_layout) = type_layout &&
+                let Variants::Multiple { variants, tag, tag_encoding, .. } =
+                    type_layout.layout.variants() &&
+                !variants.is_empty()
+            {
+                let tag_size =
+                    if let TagEncoding::Niche { .. } = tag_encoding {
+                        0
+                    } else if let Primitive::Int(i, _) = tag.primitive() {
+                        i.size().bytes()
+                    } else {
+                        span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int")
+                    };
+                variants
+                    .iter_enumerated()
+                    .map(|(variant_idx, variant_layout)| {
+                        let Adt(adt, _) = type_layout.ty.kind() else {
+                            span_bug!(cx.tcx().def_span(ty_def_id), "not an adt")
+                        };
+                        let name = adt.variant(variant_idx).name;
+                        let is_unsized = variant_layout.abi.is_unsized();
+                        let is_uninhabited = variant_layout.abi.is_uninhabited();
+                        let size = variant_layout.size.bytes() - tag_size;
+                        let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
+                        (name, type_layout_size)
+                    })
+                    .collect()
+            } else {
+                Vec::new()
+            };
+
+        let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
+            let is_unsized = layout.abi.is_unsized();
+            let is_uninhabited = layout.abi.is_uninhabited();
+            let size = layout.size.bytes();
+            TypeLayoutSize { is_unsized, is_uninhabited, size }
+        });
+
+        Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap())
+    })
+}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 93d657fd605..bccf675c14b 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -375,10 +375,7 @@ function preLoadCss(cssUrl) {
 
     function handleEscape(ev) {
         searchState.clearInputTimeout();
-        switchDisplayedElement(null);
-        if (browserSupportsHistoryApi()) {
-            history.replaceState(null, "", getNakedUrl() + window.location.hash);
-        }
+        searchState.hideResults();
         ev.preventDefault();
         searchState.defocus();
         window.hideAllModals(true); // true = reset focus for tooltips
@@ -533,9 +530,11 @@ function preLoadCss(cssUrl) {
         // ignored are included in the attribute `data-ignore-extern-crates`.
         const script = document
             .querySelector("script[data-ignore-extern-crates]");
-        const ignoreExternCrates = script ? script.getAttribute("data-ignore-extern-crates") : "";
+        const ignoreExternCrates = new Set(
+            (script ? script.getAttribute("data-ignore-extern-crates") : "").split(",")
+        );
         for (const lib of libs) {
-            if (lib === window.currentCrate || ignoreExternCrates.indexOf(lib) !== -1) {
+            if (lib === window.currentCrate || ignoreExternCrates.has(lib)) {
                 continue;
             }
             const structs = imp[lib];
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 929dae81c8d..3dc4f2149b8 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -2412,10 +2412,6 @@ function initSearch(rawSearchIndex) {
         const searchAfter500ms = () => {
             searchState.clearInputTimeout();
             if (searchState.input.value.length === 0) {
-                if (browserSupportsHistoryApi()) {
-                    history.replaceState(null, window.currentCrate + " - Rust",
-                        getNakedUrl() + window.location.hash);
-                }
                 searchState.hideResults();
             } else {
                 searchState.timeout = setTimeout(search, 500);
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 9aa75517330..d999f3b36fd 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -52,12 +52,12 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
     const files = document.createElement("div");
     files.className = "files";
     if (elem[FILES_OFFSET]) {
+        const w = window.location.href.split("#")[0];
         for (const file_text of elem[FILES_OFFSET]) {
             const file = document.createElement("a");
             file.innerText = file_text;
             file.href = rootPath + "src/" + fullPath + file_text + ".html";
             file.addEventListener("click", closeSidebarIfMobile);
-            const w = window.location.href.split("#")[0];
             if (!hasFoundFile && w === file.href) {
                 file.className = "selected";
                 dirEntry.open = true;
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
new file mode 100644
index 00000000000..58b220c7428
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -0,0 +1,53 @@
+<h2 id="layout" class="small-section-header">  {# #}
+    Layout<a href="#layout" class="anchor">§</a> {# #}
+</h2> {# #}
+<div class="docblock"> {# #}
+    {% match type_layout_size %}
+        {% when Ok(type_layout_size) %}
+            <div class="warning"> {# #}
+                <p> {# #}
+                    <strong>Note:</strong> Most layout information is <strong>completely {#+ #}
+                    unstable</strong> and may even differ between compilations. {#+ #}
+                    The only exception is types with certain <code>repr(...)</code> {#+ #}
+                    attributes. Please see the Rust Reference’s {#+ #}
+                    <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
+                    chapter for details on type layout guarantees. {# #}
+                </p> {# #}
+            </div> {# #}
+            <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
+            {% if !variants.is_empty() %}
+                <p> {# #}
+                    <strong>Size for each variant:</strong> {# #}
+                </p> {# #}
+                <ul> {# #}
+                    {% for (name, layout_size) in variants %}
+                        <li> {# #}
+                            <code>{{ name }}</code>: {#+ #}
+                            {{ layout_size|safe }}
+                        </li> {# #}
+                    {% endfor %}
+                </ul> {# #}
+            {% endif %}
+        {# This kind of layout error can occur with valid code, e.g. if you try to
+           get the layout of a generic type such as `Vec<T>`. #}
+        {% when Err(LayoutError::Unknown(_)) %}
+            <p> {# #}
+                <strong>Note:</strong> Unable to compute type layout, {#+ #}
+                possibly due to this type having generic parameters. {#+ #}
+                Layout can only be computed for concrete, fully-instantiated types. {# #}
+            </p> {# #}
+        {# This kind of error probably can't happen with valid code, but we don't
+           want to panic and prevent the docs from building, so we just let the
+           user know that we couldn't compute the layout. #}
+        {% when Err(LayoutError::SizeOverflow(_)) %}
+            <p> {# #}
+                <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+                the type was too big. {# #}
+            </p> {# #}
+        {% when Err(LayoutError::NormalizationFailure(_, _)) %}
+            <p> {# #}
+                <strong>Note:</strong> Encountered an error during type layout; {#+ #}
+                the type failed to be normalized. {# #}
+            </p> {# #}
+    {% endmatch %}
+</div> {# #}
diff --git a/src/librustdoc/html/templates/type_layout_size.html b/src/librustdoc/html/templates/type_layout_size.html
new file mode 100644
index 00000000000..9c2b39edc9f
--- /dev/null
+++ b/src/librustdoc/html/templates/type_layout_size.html
@@ -0,0 +1,12 @@
+{% if is_unsized %}
+  (unsized)
+{% else %}
+  {% if size == 1 %}
+    1 byte
+  {% else %}
+    {{ size +}} bytes
+  {% endif %}
+  {% if is_uninhabited %}
+    {# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)
+  {% endif %}
+{% endif %}