From 75d3a9ebd1a6758d7d613869e1c8f72e31676792 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Tue, 6 Sep 2022 21:10:22 +0200
Subject: [PATCH 1/8] Remove unused variable.

---
 library/core/src/num/flt2dec/strategy/grisu.rs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs
index a4cb51c6297..ed3e0edaff2 100644
--- a/library/core/src/num/flt2dec/strategy/grisu.rs
+++ b/library/core/src/num/flt2dec/strategy/grisu.rs
@@ -253,7 +253,6 @@ pub fn format_shortest_opt<'a>(
     let delta1frac = delta1 & ((1 << e) - 1);
 
     // render integral parts, while checking for the accuracy at each step.
-    let mut kappa = max_kappa as i16;
     let mut ten_kappa = max_ten_kappa; // 10^kappa
     let mut remainder = plus1int; // digits yet to be rendered
     loop {
@@ -290,12 +289,10 @@ pub fn format_shortest_opt<'a>(
         // the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`.
         if i > max_kappa as usize {
             debug_assert_eq!(ten_kappa, 1);
-            debug_assert_eq!(kappa, 0);
             break;
         }
 
         // restore invariants
-        kappa -= 1;
         ten_kappa /= 10;
         remainder = r;
     }
@@ -338,7 +335,6 @@ pub fn format_shortest_opt<'a>(
         }
 
         // restore invariants
-        kappa -= 1;
         remainder = r;
     }
 

From f67184fdcbe9ed85566b3574945df0e107b8016f Mon Sep 17 00:00:00 2001
From: Martin Geisler <martin@geisler.net>
Date: Sun, 25 Sep 2022 20:44:42 +0200
Subject: [PATCH 2/8] Consistently write `RwLock`

Before the documentation sometimes referred to an "rwlock" and sometimes to "`RwLock`".
---
 library/std/src/sync/rwlock.rs | 63 +++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 31 deletions(-)

diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 9ab781561e9..a8981233995 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -166,7 +166,7 @@ impl<T> RwLock<T> {
 }
 
 impl<T: ?Sized> RwLock<T> {
-    /// Locks this rwlock with shared read access, blocking the current thread
+    /// Locks this `RwLock` with shared read access, blocking the current thread
     /// until it can be acquired.
     ///
     /// The calling thread will be blocked until there are no more writers which
@@ -180,9 +180,10 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// # Errors
     ///
-    /// This function will return an error if the RwLock is poisoned. An RwLock
-    /// is poisoned whenever a writer panics while holding an exclusive lock.
-    /// The failure will occur immediately after the lock has been acquired.
+    /// This function will return an error if the `RwLock` is poisoned. An
+    /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+    /// lock. The failure will occur immediately after the lock has been
+    /// acquired.
     ///
     /// # Panics
     ///
@@ -214,7 +215,7 @@ impl<T: ?Sized> RwLock<T> {
         }
     }
 
-    /// Attempts to acquire this rwlock with shared read access.
+    /// Attempts to acquire this `RwLock` with shared read access.
     ///
     /// If the access could not be granted at this time, then `Err` is returned.
     /// Otherwise, an RAII guard is returned which will release the shared access
@@ -227,13 +228,13 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// # Errors
     ///
-    /// This function will return the [`Poisoned`] error if the RwLock is poisoned.
-    /// An RwLock is poisoned whenever a writer panics while holding an exclusive
-    /// lock. `Poisoned` will only be returned if the lock would have otherwise been
-    /// acquired.
+    /// This function will return the [`Poisoned`] error if the `RwLock` is
+    /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
+    /// an exclusive lock. `Poisoned` will only be returned if the lock would
+    /// have otherwise been acquired.
     ///
-    /// This function will return the [`WouldBlock`] error if the RwLock could not
-    /// be acquired because it was already locked exclusively.
+    /// This function will return the [`WouldBlock`] error if the `RwLock` could
+    /// not be acquired because it was already locked exclusively.
     ///
     /// [`Poisoned`]: TryLockError::Poisoned
     /// [`WouldBlock`]: TryLockError::WouldBlock
@@ -262,20 +263,20 @@ impl<T: ?Sized> RwLock<T> {
         }
     }
 
-    /// Locks this rwlock with exclusive write access, blocking the current
+    /// Locks this `RwLock` with exclusive write access, blocking the current
     /// thread until it can be acquired.
     ///
     /// This function will not return while other writers or other readers
     /// currently have access to the lock.
     ///
-    /// Returns an RAII guard which will drop the write access of this rwlock
+    /// Returns an RAII guard which will drop the write access of this `RwLock`
     /// when dropped.
     ///
     /// # Errors
     ///
-    /// This function will return an error if the RwLock is poisoned. An RwLock
-    /// is poisoned whenever a writer panics while holding an exclusive lock.
-    /// An error will be returned when the lock is acquired.
+    /// This function will return an error if the `RwLock` is poisoned. An
+    /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+    /// lock. An error will be returned when the lock is acquired.
     ///
     /// # Panics
     ///
@@ -302,7 +303,7 @@ impl<T: ?Sized> RwLock<T> {
         }
     }
 
-    /// Attempts to lock this rwlock with exclusive write access.
+    /// Attempts to lock this `RwLock` with exclusive write access.
     ///
     /// If the lock could not be acquired at this time, then `Err` is returned.
     /// Otherwise, an RAII guard is returned which will release the lock when
@@ -315,13 +316,13 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// # Errors
     ///
-    /// This function will return the [`Poisoned`] error if the RwLock is
-    /// poisoned. An RwLock is poisoned whenever a writer panics while holding
-    /// an exclusive lock. `Poisoned` will only be returned if the lock would have
-    /// otherwise been acquired.
+    /// This function will return the [`Poisoned`] error if the `RwLock` is
+    /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
+    /// an exclusive lock. `Poisoned` will only be returned if the lock would
+    /// have otherwise been acquired.
     ///
-    /// This function will return the [`WouldBlock`] error if the RwLock could not
-    /// be acquired because it was already locked exclusively.
+    /// This function will return the [`WouldBlock`] error if the `RwLock` could
+    /// not be acquired because it was already locked exclusively.
     ///
     /// [`Poisoned`]: TryLockError::Poisoned
     /// [`WouldBlock`]: TryLockError::WouldBlock
@@ -421,10 +422,10 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// # Errors
     ///
-    /// This function will return an error if the RwLock is poisoned. An RwLock
-    /// is poisoned whenever a writer panics while holding an exclusive lock. An
-    /// error will only be returned if the lock would have otherwise been
-    /// acquired.
+    /// This function will return an error if the `RwLock` is poisoned. An
+    /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+    /// lock. An error will only be returned if the lock would have otherwise
+    /// been acquired.
     ///
     /// # Examples
     ///
@@ -454,10 +455,10 @@ impl<T: ?Sized> RwLock<T> {
     ///
     /// # Errors
     ///
-    /// This function will return an error if the RwLock is poisoned. An RwLock
-    /// is poisoned whenever a writer panics while holding an exclusive lock. An
-    /// error will only be returned if the lock would have otherwise been
-    /// acquired.
+    /// This function will return an error if the `RwLock` is poisoned. An
+    /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+    /// lock. An error will only be returned if the lock would have otherwise
+    /// been acquired.
     ///
     /// # Examples
     ///

From b0b9f5bc269f5c5c1330bf30d25faf85741b2d49 Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Wed, 28 Sep 2022 16:54:00 +0200
Subject: [PATCH 3/8] std: never panic in `thread::park` and
 `thread::park_timeout`

---
 library/std/src/thread/mod.rs | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index ceea6986e33..54d611182e8 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -160,7 +160,7 @@ use crate::ffi::{CStr, CString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
-use crate::mem;
+use crate::mem::{self, forget};
 use crate::num::NonZeroU64;
 use crate::num::NonZeroUsize;
 use crate::panic;
@@ -849,10 +849,22 @@ pub fn sleep(dur: Duration) {
     imp::Thread::sleep(dur)
 }
 
+/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
+/// cause undefined behaviour if not handled correctly (see #102398 for context).
+struct PanicGuard;
+
+impl Drop for PanicGuard {
+    fn drop(&mut self) {
+        rtabort!("an irrecoverable error occurred while synchronizing threads")
+    }
+}
+
 /// Blocks unless or until the current thread's token is made available.
 ///
 /// A call to `park` does not guarantee that the thread will remain parked
-/// forever, and callers should be prepared for this possibility.
+/// forever, and callers should be prepared for this possibility. However,
+/// it is guaranteed that this function will not panic (it may abort the
+/// process if the implementation encounters some rare errors).
 ///
 /// # park and unpark
 ///
@@ -937,10 +949,13 @@ pub fn sleep(dur: Duration) {
 /// [`thread::park_timeout`]: park_timeout
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn park() {
+    let guard = PanicGuard;
     // SAFETY: park_timeout is called on the parker owned by this thread.
     unsafe {
         current().inner.as_ref().parker().park();
     }
+    // No panic occurred, do not abort.
+    forget(guard);
 }
 
 /// Use [`park_timeout`].
@@ -1001,10 +1016,13 @@ pub fn park_timeout_ms(ms: u32) {
 /// ```
 #[stable(feature = "park_timeout", since = "1.4.0")]
 pub fn park_timeout(dur: Duration) {
+    let guard = PanicGuard;
     // SAFETY: park_timeout is called on the parker owned by this thread.
     unsafe {
         current().inner.as_ref().parker().park_timeout(dur);
     }
+    // No panic occurred, do not abort.
+    forget(guard);
 }
 
 ////////////////////////////////////////////////////////////////////////////////

From 78b577c065f71c7ad30a70c8c65c7ff561fee852 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 2 Oct 2022 18:30:55 +0200
Subject: [PATCH 4/8] scoped threads: pass closure through MaybeUninit to avoid
 invalid dangling references

---
 library/std/src/thread/mod.rs | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index ceea6986e33..809b835345f 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -499,6 +499,31 @@ impl Builder {
         let output_capture = crate::io::set_output_capture(None);
         crate::io::set_output_capture(output_capture.clone());
 
+        // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*.
+        // See <https://github.com/rust-lang/rust/issues/101983> for more details.
+        // To prevent leaks we use a wrapper that drops its contents.
+        #[repr(transparent)]
+        struct MaybeDangling<T>(mem::MaybeUninit<T>);
+        impl<T> MaybeDangling<T> {
+            fn new(x: T) -> Self {
+                MaybeDangling(mem::MaybeUninit::new(x))
+            }
+            fn into_inner(self) -> T {
+                // SAFETY: we are always initiailized.
+                let ret = unsafe { self.0.assume_init_read() };
+                // Make sure we don't drop.
+                mem::forget(self);
+                ret
+            }
+        }
+        impl<T> Drop for MaybeDangling<T> {
+            fn drop(&mut self) {
+                // SAFETY: we are always initiailized.
+                unsafe { self.0.assume_init_drop() };
+            }
+        }
+
+        let f = MaybeDangling::new(f);
         let main = move || {
             if let Some(name) = their_thread.cname() {
                 imp::Thread::set_name(name);
@@ -506,6 +531,8 @@ impl Builder {
 
             crate::io::set_output_capture(output_capture);
 
+            // SAFETY: we constructed `f` initialized.
+            let f = f.into_inner();
             // SAFETY: the stack guard passed is the one for the current thread.
             // This means the current thread's stack and the new thread's stack
             // are properly set and protected from each other.
@@ -518,6 +545,12 @@ impl Builder {
             // same `JoinInner` as this closure meaning the mutation will be
             // safe (not modify it and affect a value far away).
             unsafe { *their_packet.result.get() = Some(try_result) };
+            // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that
+            // will call `decrement_num_running_threads` and therefore signal that this thread is
+            // done.
+            drop(their_packet);
+            // Here, the lifetime `'a` and even `'scope` can end. `main` keeps running for a bit
+            // after that before returning itself.
         };
 
         if let Some(scope_data) = &my_packet.scope {

From 9fb509e8844301ec0a2a2d8bfa42f47f352d8688 Mon Sep 17 00:00:00 2001
From: Rageking8 <tomleetyt@gmail.com>
Date: Tue, 4 Oct 2022 00:29:29 +0800
Subject: [PATCH 5/8] fix backtrace small typo

---
 library/std/src/backtrace.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 5cf6ec81789..34b57c37635 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -14,8 +14,8 @@
 //! Backtraces are attempted to be as accurate as possible, but no guarantees
 //! are provided about the exact accuracy of a backtrace. Instruction pointers,
 //! symbol names, filenames, line numbers, etc, may all be incorrect when
-//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
-//! are always welcome to indicate areas of improvement!
+//! reported. Accuracy is attempted on a best-effort basis, however, any bug
+//! reports are always welcome to indicate areas of improvement!
 //!
 //! For most platforms a backtrace with a filename/line number requires that
 //! programs be compiled with debug information. Without debug information
@@ -39,7 +39,7 @@
 //! default. Its behavior is governed by two environment variables:
 //!
 //! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
-//!   will never capture a backtrace. Any other value this is set to will enable
+//!   will never capture a backtrace. Any other value set will enable
 //!   `Backtrace::capture`.
 //!
 //! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable

From a474ec50b7010d289d103242a63c806ed6f01c2e Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 9 Oct 2022 20:26:39 +0000
Subject: [PATCH 6/8] Move lifetime resolution module to rustc_hir_analysis.

---
 compiler/rustc_hir_analysis/src/collect.rs      |  2 ++
 .../src/collect}/lifetimes.rs                   | 17 +++--------------
 compiler/rustc_interface/src/passes.rs          |  1 -
 compiler/rustc_resolve/src/late.rs              |  1 -
 compiler/rustc_resolve/src/lib.rs               |  5 -----
 5 files changed, 5 insertions(+), 21 deletions(-)
 rename compiler/{rustc_resolve/src/late => rustc_hir_analysis/src/collect}/lifetimes.rs (99%)

diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 6976c5a0edb..98bcdcf6520 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -46,6 +46,7 @@ use std::iter;
 
 mod generics_of;
 mod item_bounds;
+mod lifetimes;
 mod predicates_of;
 mod type_of;
 
@@ -57,6 +58,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 }
 
 pub fn provide(providers: &mut Providers) {
+    lifetimes::provide(providers);
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
similarity index 99%
rename from compiler/rustc_resolve/src/late/lifetimes.rs
rename to compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index c18d5d06d64..c1214698cf7 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -32,8 +32,6 @@ trait RegionExt {
     fn id(&self) -> Option<DefId>;
 
     fn shifted(self, amount: u32) -> Region;
-
-    fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
 }
 
 impl RegionExt for Region {
@@ -69,15 +67,6 @@ impl RegionExt for Region {
             _ => self,
         }
     }
-
-    fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
-        match self {
-            Region::LateBound(debruijn, index, id) => {
-                Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id)
-            }
-            _ => self,
-        }
-    }
 }
 
 /// Maps the id of each lifetime reference to the lifetime decl
@@ -101,8 +90,8 @@ struct NamedRegionMap {
     late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
 }
 
-pub(crate) struct LifetimeContext<'a, 'tcx> {
-    pub(crate) tcx: TyCtxt<'tcx>,
+struct LifetimeContext<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
     map: &'a mut NamedRegionMap,
     scope: ScopeRef<'a>,
 
@@ -234,7 +223,7 @@ type ScopeRef<'a> = &'a Scope<'a>;
 
 const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
 
-pub fn provide(providers: &mut ty::query::Providers) {
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         resolve_lifetimes_trait_definition,
         resolve_lifetimes,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index ad3e020b581..8fd4224ca38 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -739,7 +739,6 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
     ty::provide(providers);
     traits::provide(providers);
     rustc_passes::provide(providers);
-    rustc_resolve::provide(providers);
     rustc_traits::provide(providers);
     rustc_ty_utils::provide(providers);
     rustc_metadata::provide(providers);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 989a827ef7d..c08f4a7204d 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -34,7 +34,6 @@ use std::collections::{hash_map::Entry, BTreeSet};
 use std::mem::{replace, take};
 
 mod diagnostics;
-pub(crate) mod lifetimes;
 
 type Res = def::Res<NodeId>;
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 9173c3692ce..095a57ae24f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -42,7 +42,6 @@ use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::span_bug;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn};
@@ -2082,7 +2081,3 @@ impl Finalize {
         Finalize { node_id, path_span, root_span, report_private: true }
     }
 }
-
-pub fn provide(providers: &mut Providers) {
-    late::lifetimes::provide(providers);
-}

From b63b02f8728259c3b67d1f6ca7d1845892b86a9e Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Mon, 10 Oct 2022 11:37:19 -0700
Subject: [PATCH 7/8] rustdoc: remove unneeded `<div>` wrapper from sidebar DOM

When this was added, the sidebar had a bit more complex style. It can be
removed, now.
---
 src/librustdoc/html/render/mod.rs             | 23 +++++-----------
 src/librustdoc/html/static/css/rustdoc.css    |  5 ++--
 src/librustdoc/html/static/js/main.js         | 26 ++++++++-----------
 src/test/rustdoc-gui/headings.goml            |  4 +--
 src/test/rustdoc-gui/sidebar.goml             | 20 +++++++-------
 .../strip-enum-variant.no-not-shown.html      |  2 +-
 src/test/rustdoc/strip-enum-variant.rs        |  2 +-
 7 files changed, 35 insertions(+), 47 deletions(-)

diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4bbb322d370..5e4226042ec 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1853,12 +1853,12 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
 
     buffer.write_str("<div class=\"sidebar-elems\">");
     if it.is_crate() {
-        write!(buffer, "<div class=\"block\"><ul>");
+        write!(buffer, "<ul class=\"block\">");
         if let Some(ref version) = cx.cache().crate_version {
             write!(buffer, "<li class=\"version\">Version {}</li>", Escape(version));
         }
         write!(buffer, "<li><a id=\"all-types\" href=\"all.html\">All Items</a></li>");
-        buffer.write_str("</ul></div>");
+        buffer.write_str("</ul>");
     }
 
     match *it.kind {
@@ -2259,7 +2259,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
 }
 
 /// Don't call this function directly!!! Use `print_sidebar_title` or `print_sidebar_block` instead!
-fn print_sidebar_title_inner(buf: &mut Buffer, id: &str, title: &str) {
+fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
     write!(
         buf,
         "<h3 class=\"sidebar-title\">\
@@ -2269,25 +2269,18 @@ fn print_sidebar_title_inner(buf: &mut Buffer, id: &str, title: &str) {
     );
 }
 
-fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
-    buf.push_str("<div class=\"block\">");
-    print_sidebar_title_inner(buf, id, title);
-    buf.push_str("</div>");
-}
-
 fn print_sidebar_block(
     buf: &mut Buffer,
     id: &str,
     title: &str,
     items: impl Iterator<Item = impl fmt::Display>,
 ) {
-    buf.push_str("<div class=\"block\">");
-    print_sidebar_title_inner(buf, id, title);
-    buf.push_str("<ul>");
+    print_sidebar_title(buf, id, title);
+    buf.push_str("<ul class=\"block\">");
     for item in items {
         write!(buf, "<li>{}</li>", item);
     }
-    buf.push_str("</ul></div>");
+    buf.push_str("</ul>");
 }
 
 fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
@@ -2676,9 +2669,7 @@ pub(crate) fn sidebar_module_like(buf: &mut Buffer, item_sections_in_use: FxHash
         write!(
             buf,
             "<section>\
-                 <div class=\"block\">\
-                     <ul>{}</ul>\
-                 </div>\
+                 <ul class=\"block\">{}</ul>\
              </section>",
             sidebar
         );
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index eb64147d906..386977c6f8e 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -501,13 +501,14 @@ img {
 	width: 100px;
 }
 
-.block ul, .block li {
+ul.block, .block li {
 	padding: 0;
 	margin: 0;
 	list-style: none;
 }
 
 .block a,
+.sidebar h3 a,
 h2.location a {
 	display: block;
 	padding: 0.25rem;
@@ -769,7 +770,7 @@ h2.small-section-header > .anchor {
 	text-decoration: underline;
 }
 
-.block a.current.crate { font-weight: 500; }
+.crate.block a.current { font-weight: 500; }
 
 /*  In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap
 	as much as needed on mobile (see
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 359dd41b13f..0180c0ead8d 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -442,12 +442,10 @@ function loadCss(cssFileName) {
                 return;
             }
 
-            const div = document.createElement("div");
-            div.className = "block " + shortty;
             const h3 = document.createElement("h3");
             h3.innerHTML = `<a href="index.html#${id}">${longty}</a>`;
-            div.appendChild(h3);
             const ul = document.createElement("ul");
+            ul.className = "block " + shortty;
 
             for (const item of filtered) {
                 const name = item[0];
@@ -473,8 +471,8 @@ function loadCss(cssFileName) {
                 li.appendChild(link);
                 ul.appendChild(li);
             }
-            div.appendChild(ul);
-            sidebar.appendChild(div);
+            sidebar.appendChild(h3);
+            sidebar.appendChild(ul);
         }
 
         if (sidebar) {
@@ -592,27 +590,25 @@ function loadCss(cssFileName) {
             return;
         }
         // Draw a convenient sidebar of known crates if we have a listing
-        const div = document.createElement("div");
-        div.className = "block crate";
-        div.innerHTML = "<h3>Crates</h3>";
+        const h3 = document.createElement("h3");
+        h3.innerHTML = "Crates";
         const ul = document.createElement("ul");
-        div.appendChild(ul);
+        ul.className = "block crate";
 
         for (const crate of window.ALL_CRATES) {
-            let klass = "crate";
-            if (window.rootPath !== "./" && crate === window.currentCrate) {
-                klass += " current";
-            }
             const link = document.createElement("a");
             link.href = window.rootPath + crate + "/index.html";
-            link.className = klass;
+            if (window.rootPath !== "./" && crate === window.currentCrate) {
+                link.className = "current";
+            }
             link.textContent = crate;
 
             const li = document.createElement("li");
             li.appendChild(link);
             ul.appendChild(li);
         }
-        sidebarElems.appendChild(div);
+        sidebarElems.appendChild(h3);
+        sidebarElems.appendChild(ul);
     }
 
 
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 3e97bb78c78..9a77d8bbd15 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -106,8 +106,8 @@ assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "14px"})
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
 
-assert-text: (".sidebar .mod h3", "Modules")
-assert-css: (".sidebar .mod h3", {"border-bottom-width": "0px"}, ALL)
+assert-text: ("//ul[@class='block mod']/preceding-sibling::h3", "Modules")
+assert-css: ("//ul[@class='block mod']/preceding-sibling::h3", {"border-bottom-width": "0px"}, ALL)
 
 goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html"
 
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index ad1fb6df89a..54193234af9 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -12,7 +12,7 @@ assert-count: (".sidebar .location", 1)
 assert-text: ("#all-types", "All Items")
 assert-css: ("#all-types", {"color": "rgb(53, 109, 164)"})
 // We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems ul.crate > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
 assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Re-exports")
 assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Modules")
@@ -41,21 +41,21 @@ assert-property: ("html", {"scrollTop": "0"})
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
-assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(53, 109, 164)"})
-click: ".sidebar-elems .crate > ul > li:first-child > a"
+assert-css: (".sidebar-elems ul.crate > li:first-child > a", {"color": "rgb(53, 109, 164)"})
+click: ".sidebar-elems ul.crate > li:first-child > a"
 
 // PAGE: lib2/index.html
 goto: "file://" + |DOC_PATH| + "/lib2/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems ul.crate > li > a.current", "lib2")
 // We now go to the "foobar" function page.
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(2)", "Structs")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(3)", "Traits")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(4)", "Functions")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(5)", "Type Definitions")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(3)", "Traits")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(4)", "Functions")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(5)", "Type Definitions")
 assert-text: ("#functions + .item-table .item-left > a", "foobar")
 click: "#functions + .item-table .item-left > a"
 
@@ -90,7 +90,7 @@ assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29})
 // appropriate anchor in index.html.
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
-click: ".block.mod h3 a"
+click: "//ul[@class='block mod']/preceding-sibling::h3/a"
 // PAGE: index.html
 assert-css: ("#modules", {"background-color": "rgb(253, 255, 211)"})
 
diff --git a/src/test/rustdoc/strip-enum-variant.no-not-shown.html b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
index c4ee1a99114..782198956a0 100644
--- a/src/test/rustdoc/strip-enum-variant.no-not-shown.html
+++ b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
@@ -1 +1 @@
-<ul><li><a href="#variant.Shown">Shown</a></li></ul>
\ No newline at end of file
+<ul class="block"><li><a href="#variant.Shown">Shown</a></li></ul>
\ No newline at end of file
diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs
index f82ffdfeda5..8753a7dc613 100644
--- a/src/test/rustdoc/strip-enum-variant.rs
+++ b/src/test/rustdoc/strip-enum-variant.rs
@@ -3,7 +3,7 @@
 // @!has - '//code' 'NotShown'
 // @has - '//code' '// some variants omitted'
 // Also check that `NotShown` isn't displayed in the sidebar.
-// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]/ul'
+// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]'
 pub enum MyThing {
     Shown,
     #[doc(hidden)]

From 44f466cb08650a721d06dece85385506633d55fc Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Mon, 10 Oct 2022 17:53:27 -0700
Subject: [PATCH 8/8] Remove outdated comment

---
 src/librustdoc/html/render/mod.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 5e4226042ec..1e162bf314b 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2258,7 +2258,6 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
     }
 }
 
-/// Don't call this function directly!!! Use `print_sidebar_title` or `print_sidebar_block` instead!
 fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
     write!(
         buf,