about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--compiler/rustc_error_messages/locales/en-US/query_system.ftl3
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs29
-rw-r--r--compiler/rustc_query_system/src/error.rs20
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs21
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs6
-rw-r--r--library/core/src/array/mod.rs48
-rw-r--r--library/core/src/primitive_docs.rs23
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/primitive_docs.rs23
m---------library/stdarch0
-rw-r--r--src/bootstrap/bootstrap.py15
-rw-r--r--src/bootstrap/builder.rs13
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/native.rs9
-rw-r--r--src/bootstrap/tool.rs32
-rw-r--r--src/ci/github-actions/ci.yml2
-rw-r--r--src/librustdoc/html/render/mod.rs35
-rw-r--r--src/librustdoc/html/render/write_shared.rs4
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css52
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css40
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css31
-rw-r--r--src/librustdoc/html/static/css/themes/light.css31
-rw-r--r--src/test/rustdoc-gui/links-color.goml85
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.fixed10
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.rs10
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.stderr24
-rw-r--r--src/test/rustdoc/index-page.rs4
-rw-r--r--src/test/ui/query-system/query_depth.rs31
-rw-r--r--src/test/ui/query-system/query_depth.stderr11
31 files changed, 475 insertions, 153 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 69f96bcbe63..22fe7183a01 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -507,6 +507,10 @@ name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-core",
+]
 
 [[package]]
 name = "chalk-derive"
@@ -4613,7 +4617,7 @@ version = "0.0.0"
 dependencies = [
  "addr2line 0.16.0",
  "alloc",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "compiler_builtins",
  "core",
  "dlmalloc",
@@ -4637,7 +4641,7 @@ dependencies = [
 name = "std_detect"
 version = "0.1.5"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "compiler_builtins",
  "libc",
  "rustc-std-workspace-alloc",
diff --git a/compiler/rustc_error_messages/locales/en-US/query_system.ftl b/compiler/rustc_error_messages/locales/en-US/query_system.ftl
index 167704e46c0..b914ba52a73 100644
--- a/compiler/rustc_error_messages/locales/en-US/query_system.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/query_system.ftl
@@ -23,3 +23,6 @@ query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
 query_system_cycle_which_requires = ...which requires {$desc}...
 
 query_system_query_overflow = queries overflow the depth limit!
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6f39bbfc0dc..d819f4774d5 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -19,8 +19,10 @@ use rustc_query_system::query::{
     force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
     QuerySideEffects, QueryStackFrame,
 };
-use rustc_query_system::Value;
+use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value};
 use rustc_serialize::Decodable;
+use rustc_session::Limit;
+use rustc_span::def_id::LOCAL_CRATE;
 use std::any::Any;
 use std::num::NonZeroU64;
 use thin_vec::ThinVec;
@@ -109,7 +111,7 @@ impl QueryContext for QueryCtxt<'_> {
         // when accessing the `ImplicitCtxt`.
         tls::with_related_context(**self, move |current_icx| {
             if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
-                self.depth_limit_error();
+                self.depth_limit_error(token);
             }
 
             // Update the `ImplicitCtxt` to point to our new query job.
@@ -127,6 +129,29 @@ impl QueryContext for QueryCtxt<'_> {
             })
         })
     }
+
+    fn depth_limit_error(&self, job: QueryJobId) {
+        let mut span = None;
+        let mut layout_of_depth = None;
+        if let Some(map) = self.try_collect_active_jobs() {
+            if let Some((info, depth)) = job.try_find_layout_root(map) {
+                span = Some(info.job.span);
+                layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth });
+            }
+        }
+
+        let suggested_limit = match self.recursion_limit() {
+            Limit(0) => Limit(2),
+            limit => limit * 2,
+        };
+
+        self.sess.emit_fatal(QueryOverflow {
+            span,
+            layout_of_depth,
+            suggested_limit,
+            crate_name: self.crate_name(LOCAL_CRATE),
+        });
+    }
 }
 
 impl<'tcx> QueryCtxt<'tcx> {
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 3fb06cbedbd..bececca7585 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -1,5 +1,6 @@
 use rustc_errors::AddSubdiagnostic;
-use rustc_span::Span;
+use rustc_session::Limit;
+use rustc_span::{Span, Symbol};
 
 pub struct CycleStack {
     pub span: Span,
@@ -76,5 +77,20 @@ pub struct IncrementCompilation {
 }
 
 #[derive(SessionDiagnostic)]
+#[help]
 #[diag(query_system::query_overflow)]
-pub struct QueryOverflow;
+pub struct QueryOverflow {
+    #[primary_span]
+    pub span: Option<Span>,
+    #[subdiagnostic]
+    pub layout_of_depth: Option<LayoutOfDepth>,
+    pub suggested_limit: Limit,
+    pub crate_name: Symbol,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[note(query_system::layout_of_depth)]
+pub struct LayoutOfDepth {
+    pub desc: String,
+    pub depth: usize,
+}
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index f92c3831f26..5987651322a 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -23,4 +23,6 @@ pub mod query;
 mod values;
 
 pub use error::HandleCycleError;
+pub use error::LayoutOfDepth;
+pub use error::QueryOverflow;
 pub use values::Value;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 45b4079fb54..95305eabd0d 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -59,6 +59,7 @@ impl QueryJobId {
     }
 }
 
+#[derive(Clone)]
 pub struct QueryJobInfo {
     pub query: QueryStackFrame,
     pub job: QueryJob,
@@ -116,10 +117,10 @@ impl QueryJob {
     }
 }
 
-#[cfg(not(parallel_compiler))]
 impl QueryJobId {
     #[cold]
     #[inline(never)]
+    #[cfg(not(parallel_compiler))]
     pub(super) fn find_cycle_in_stack(
         &self,
         query_map: QueryMap,
@@ -156,6 +157,24 @@ impl QueryJobId {
 
         panic!("did not find a cycle")
     }
+
+    #[cold]
+    #[inline(never)]
+    pub fn try_find_layout_root(&self, query_map: QueryMap) -> Option<(QueryJobInfo, usize)> {
+        let mut last_layout = None;
+        let mut current_id = Some(*self);
+        let mut depth = 0;
+
+        while let Some(id) = current_id {
+            let info = query_map.get(&id).unwrap();
+            if info.query.name == "layout_of" {
+                depth += 1;
+                last_layout = Some((info.clone(), depth));
+            }
+            current_id = info.job.parent;
+        }
+        last_layout
+    }
 }
 
 #[cfg(parallel_compiler)]
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 0b07bb64b6a..7a96c53b604 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -14,7 +14,7 @@ pub use self::caches::{
 mod config;
 pub use self::config::{QueryConfig, QueryDescription, QueryVTable};
 
-use crate::dep_graph::{DepContext, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
+use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
 use rustc_data_structures::sync::Lock;
 use rustc_errors::Diagnostic;
 use rustc_hir::def::DefKind;
@@ -123,7 +123,5 @@ pub trait QueryContext: HasDepContext {
         compute: impl FnOnce() -> R,
     ) -> R;
 
-    fn depth_limit_error(&self) {
-        self.dep_context().sess().emit_fatal(crate::error::QueryOverflow);
-    }
+    fn depth_limit_error(&self, job: QueryJobId);
 }
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 9effb379016..165b9d24d93 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -184,6 +184,18 @@ impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
     }
 }
 
+/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if
+/// `slice.len() == N`.
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(bytes_head));
+///
+/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
+/// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 impl<T, const N: usize> TryFrom<&[T]> for [T; N]
 where
@@ -196,6 +208,18 @@ where
     }
 }
 
+/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
+/// Succeeds if `slice.len() == N`.
+///
+/// ```
+/// let mut bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(bytes_head));
+///
+/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
+/// ```
 #[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
 impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
 where
@@ -208,6 +232,18 @@ where
     }
 }
 
+/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
+/// `slice.len() == N`.
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
+///
+/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
+/// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
     type Error = TryFromSliceError;
@@ -223,6 +259,18 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
     }
 }
 
+/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
+/// `&mut [T]`. Succeeds if `slice.len() == N`.
+///
+/// ```
+/// let mut bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
+///
+/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
+/// ```
 #[stable(feature = "try_from", since = "1.34.0")]
 impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
     type Error = TryFromSliceError;
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 242f44ade8a..331714a993c 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -611,7 +611,19 @@ mod prim_pointer {}
 ///
 /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
 /// an array. Indeed, this provides most of the API for working with arrays.
-/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// Slices have a dynamic size and do not coerce to arrays. Instead, use
+/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
+///
+/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
+/// array implementations) succeed if the input slice length is the same as the result
+/// array length. They optimize especially well when the optimizer can easily determine
+/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
+/// [TryFrom](crate::convert::TryFrom) returning:
+///
+/// - `[T; N]` copies from the slice's elements
+/// - `&[T; N]` references the original slice's elements
+/// - `&mut [T; N]` references the original slice's elements
 ///
 /// You can move elements out of an array with a [slice pattern]. If you want
 /// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
 /// for x in &array { }
 /// ```
 ///
+/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
+/// a slice:
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
+/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
+/// ```
+///
 /// You can use a [slice pattern] to move elements out of an array:
 ///
 /// ```
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 324ecc80477..b8c35ecd349 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -11,7 +11,7 @@ crate-type = ["dylib", "rlib"]
 
 [dependencies]
 alloc = { path = "../alloc" }
-cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
+cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 242f44ade8a..331714a993c 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -611,7 +611,19 @@ mod prim_pointer {}
 ///
 /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
 /// an array. Indeed, this provides most of the API for working with arrays.
-/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// Slices have a dynamic size and do not coerce to arrays. Instead, use
+/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
+///
+/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
+/// array implementations) succeed if the input slice length is the same as the result
+/// array length. They optimize especially well when the optimizer can easily determine
+/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
+/// [TryFrom](crate::convert::TryFrom) returning:
+///
+/// - `[T; N]` copies from the slice's elements
+/// - `&[T; N]` references the original slice's elements
+/// - `&mut [T; N]` references the original slice's elements
 ///
 /// You can move elements out of an array with a [slice pattern]. If you want
 /// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
 /// for x in &array { }
 /// ```
 ///
+/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
+/// a slice:
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
+/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
+/// ```
+///
 /// You can use a [slice pattern] to move elements out of an array:
 ///
 /// ```
diff --git a/library/stdarch b/library/stdarch
-Subproject 42df7394d38bc7b945116ea3ad8a7cbcd1db50a
+Subproject 699c093a42283c07e9763b4c19439a900ae2d32
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index cc08ae5f99f..350d87d58a4 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -732,9 +732,19 @@ class RustBuild(object):
             (os.pathsep + env["LIBRARY_PATH"]) \
             if "LIBRARY_PATH" in env else ""
 
+        # Export Stage0 snapshot compiler related env variables
+        build_section = "target.{}".format(self.build)
+        host_triple_sanitized = self.build.replace("-", "_")
+        var_data = {
+            "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib"
+        }
+        for var_name, toml_key in var_data.items():
+            toml_val = self.get_toml(toml_key, build_section)
+            if toml_val != None:
+                env["{}_{}".format(var_name, host_triple_sanitized)] = toml_val
+
         # preserve existing RUSTFLAGS
         env.setdefault("RUSTFLAGS", "")
-        build_section = "target.{}".format(self.build)
         target_features = []
         if self.get_toml("crt-static", build_section) == "true":
             target_features += ["+crt-static"]
@@ -742,9 +752,6 @@ class RustBuild(object):
             target_features += ["-crt-static"]
         if target_features:
             env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features))
-        target_linker = self.get_toml("linker", build_section)
-        if target_linker is not None:
-            env["RUSTFLAGS"] += " -C linker=" + target_linker
         env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
         env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros"
         if self.get_toml("deny-warnings", "rust") != "false":
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 14e8ebd6876..b654db6dbe9 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1940,25 +1940,26 @@ impl<'a> Builder<'a> {
                     _ => s.display().to_string(),
                 }
             };
+            let triple_underscored = target.triple.replace("-", "_");
             let cc = ccacheify(&self.cc(target));
-            cargo.env(format!("CC_{}", target.triple), &cc);
+            cargo.env(format!("CC_{}", triple_underscored), &cc);
 
             let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" ");
-            cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
+            cargo.env(format!("CFLAGS_{}", triple_underscored), &cflags);
 
             if let Some(ar) = self.ar(target) {
                 let ranlib = format!("{} s", ar.display());
                 cargo
-                    .env(format!("AR_{}", target.triple), ar)
-                    .env(format!("RANLIB_{}", target.triple), ranlib);
+                    .env(format!("AR_{}", triple_underscored), ar)
+                    .env(format!("RANLIB_{}", triple_underscored), ranlib);
             }
 
             if let Ok(cxx) = self.cxx(target) {
                 let cxx = ccacheify(&cxx);
                 let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" ");
                 cargo
-                    .env(format!("CXX_{}", target.triple), &cxx)
-                    .env(format!("CXXFLAGS_{}", target.triple), cxxflags);
+                    .env(format!("CXX_{}", triple_underscored), &cxx)
+                    .env(format!("CXXFLAGS_{}", triple_underscored), cxxflags);
             }
         }
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index cc0cf12bd18..fade44ecb15 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1307,10 +1307,6 @@ impl Build {
         self.package_vers(&self.version)
     }
 
-    fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool {
-        target.contains("linux-gnu") || target.contains("apple-darwin")
-    }
-
     /// Returns the `version` string associated with this compiler for Rust
     /// itself.
     ///
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 62b56994afe..d6ee6d489cf 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -423,12 +423,7 @@ impl Step for Llvm {
         // which saves both memory during parallel links and overall disk space
         // for the tools. We don't do this on every platform as it doesn't work
         // equally well everywhere.
-        //
-        // If we're not linking rustc to a dynamic LLVM, though, then don't link
-        // tools to it.
-        let llvm_link_shared =
-            builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared();
-        if llvm_link_shared {
+        if builder.llvm_link_shared() {
             cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
         }
 
@@ -553,7 +548,7 @@ impl Step for Llvm {
         // libLLVM.dylib will be built. However, llvm-config will still look
         // for a versioned path like libLLVM-14.dylib. Manually create a symbolic
         // link to make llvm-config happy.
-        if llvm_link_shared && target.contains("apple-darwin") {
+        if builder.llvm_link_shared() && target.contains("apple-darwin") {
             let mut cmd = Command::new(&build_llvm_config);
             let version = output(cmd.arg("--version"));
             let major = version.split('.').next().unwrap();
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 7d4ed24b648..5d0c7d2bd9d 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -746,14 +746,18 @@ impl Step for RustAnalyzerProcMacroSrv {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("src/tools/rust-analyzer").default_condition(
-            builder.config.extended
-                && builder
-                    .config
-                    .tools
-                    .as_ref()
-                    .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")),
-        )
+
+        // Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
+        run.path("src/tools/rust-analyzer")
+            .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
+            .default_condition(
+                builder.config.extended
+                    && builder.config.tools.as_ref().map_or(true, |tools| {
+                        tools.iter().any(|tool| {
+                            tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
+                        })
+                    }),
+            )
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -764,7 +768,7 @@ impl Step for RustAnalyzerProcMacroSrv {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
-        builder.ensure(ToolBuild {
+        let path = builder.ensure(ToolBuild {
             compiler: self.compiler,
             target: self.target,
             tool: "rust-analyzer-proc-macro-srv",
@@ -773,7 +777,15 @@ impl Step for RustAnalyzerProcMacroSrv {
             extra_features: vec!["proc-macro-srv/sysroot-abi".to_owned()],
             is_optional_tool: false,
             source_type: SourceType::InTree,
-        })
+        })?;
+
+        // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
+        // so that r-a can use it.
+        let libexec_path = builder.sysroot(self.compiler).join("libexec");
+        t!(fs::create_dir_all(&libexec_path));
+        builder.copy(&path, &libexec_path.join("rust-analyzer-proc-macro-srv"));
+
+        Some(path)
     }
 }
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 6e4b0b0c2c3..7826fd51409 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -286,7 +286,7 @@ jobs:
 
           - name: x86_64-gnu-llvm-13
             <<: *job-linux-xl
-            
+
           - name: x86_64-gnu-tools
             env:
               CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 1e6f20d2b49..ced0ebdbb86 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -294,16 +294,15 @@ impl AllTypes {
 
 impl AllTypes {
     fn print(self, f: &mut Buffer) {
-        fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str, class: &str) {
+        fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str) {
             if !e.is_empty() {
                 let mut e: Vec<&ItemEntry> = e.iter().collect();
                 e.sort();
                 write!(
                     f,
-                    "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">",
+                    "<h3 id=\"{}\">{}</h3><ul class=\"all-items\">",
                     title.replace(' ', "-"), // IDs cannot contain whitespaces.
-                    title,
-                    class
+                    title
                 );
 
                 for s in e.iter() {
@@ -321,20 +320,20 @@ impl AllTypes {
         );
         // Note: print_entries does not escape the title, because we know the current set of titles
         // doesn't require escaping.
-        print_entries(f, &self.structs, "Structs", "structs");
-        print_entries(f, &self.enums, "Enums", "enums");
-        print_entries(f, &self.unions, "Unions", "unions");
-        print_entries(f, &self.primitives, "Primitives", "primitives");
-        print_entries(f, &self.traits, "Traits", "traits");
-        print_entries(f, &self.macros, "Macros", "macros");
-        print_entries(f, &self.attributes, "Attribute Macros", "attributes");
-        print_entries(f, &self.derives, "Derive Macros", "derives");
-        print_entries(f, &self.functions, "Functions", "functions");
-        print_entries(f, &self.typedefs, "Typedefs", "typedefs");
-        print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases");
-        print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types");
-        print_entries(f, &self.statics, "Statics", "statics");
-        print_entries(f, &self.constants, "Constants", "constants")
+        print_entries(f, &self.structs, "Structs");
+        print_entries(f, &self.enums, "Enums");
+        print_entries(f, &self.unions, "Unions");
+        print_entries(f, &self.primitives, "Primitives");
+        print_entries(f, &self.traits, "Traits");
+        print_entries(f, &self.macros, "Macros");
+        print_entries(f, &self.attributes, "Attribute Macros");
+        print_entries(f, &self.derives, "Derive Macros");
+        print_entries(f, &self.functions, "Functions");
+        print_entries(f, &self.typedefs, "Typedefs");
+        print_entries(f, &self.trait_aliases, "Trait Aliases");
+        print_entries(f, &self.opaque_tys, "Opaque Types");
+        print_entries(f, &self.statics, "Statics");
+        print_entries(f, &self.constants, "Constants");
     }
 }
 
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index fc4d46fe6b6..1c88528aa20 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -519,12 +519,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
             let content = format!(
                 "<h1 class=\"fqn\">\
                      <span class=\"in-band\">List of all crates</span>\
-                </h1><ul class=\"crate mod\">{}</ul>",
+                </h1><ul class=\"all-items\">{}</ul>",
                 krates
                     .iter()
                     .map(|s| {
                         format!(
-                            "<li><a class=\"crate mod\" href=\"{}index.html\">{}</a></li>",
+                            "<li><a href=\"{}index.html\">{}</a></li>",
                             ensure_trailing_slash(s),
                             s
                         )
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 3995c9fdb01..84ed056d0e1 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -207,7 +207,6 @@ a.source,
 .out-of-band,
 span.since,
 details.rustdoc-toggle > summary::before,
-.content ul.crate a.crate,
 a.srclink,
 #help-button > button,
 details.rustdoc-toggle.top-doc > summary,
@@ -218,7 +217,7 @@ details.rustdoc-toggle.non-exhaustive > summary::before,
 .more-examples-toggle summary, .more-examples-toggle .hide-more,
 .example-links a,
 /* This selector is for the items listed in the "all items" page. */
-#main-content > ul.docblock > li > a {
+ul.all-items {
 	font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
 }
 
@@ -241,6 +240,49 @@ pre.rust a,
 	color: var(--main-color);
 }
 
+.content span.enum, .content a.enum,
+.content span.struct, .content a.struct,
+.content span.union, .content a.union,
+.content span.primitive, .content a.primitive,
+.content span.type, .content a.type,
+.content span.foreigntype, .content a.foreigntype {
+	color: var(--type-link-color);
+}
+
+.content span.trait, .content a.trait,
+.content span.traitalias, .content a.traitalias {
+	color: var(--trait-link-color);
+}
+
+.content span.associatedtype, .content a.associatedtype,
+.content span.constant, .content a.constant,
+.content span.static, .content a.static {
+	color: var(--assoc-item-link-color);
+}
+
+.content span.fn, .content a.fn,
+.content .fnname {
+	color: var(--function-link-color);
+}
+
+.content span.attr, .content a.attr,
+.content span.derive, .content a.derive,
+.content span.macro, .content a.macro {
+	color: var(--macro-link-color);
+}
+
+.content span.mod, .content a.mod, .block a.current.mod {
+	color: var(--mod-link-color);
+}
+
+.content span.keyword, .content a.keyword {
+	color: var(--keyword-link-color);
+}
+
+a {
+	color: var(--link-color);
+}
+
 ol, ul {
 	padding-left: 24px;
 }
@@ -786,6 +828,7 @@ h2.small-section-header > .anchor {
 	content: 'ยง';
 }
 
+.all-items a:hover,
 .docblock a:not(.srclink):not(.test-arrow):not(.scrape-help):hover,
 .docblock-short a:not(.srclink):not(.test-arrow):not(.scrape-help):hover, .item-info a {
 	text-decoration: underline;
@@ -1515,10 +1558,7 @@ kbd {
 	cursor: default;
 }
 
-#main-content > ul {
-	padding-left: 10px;
-}
-#main-content > ul > li {
+ul.all-items > li {
 	list-style: none;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index c292a8a7ef7..e7a898e9fa6 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -27,6 +27,14 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--type-link-color: #ffa0a5;
+	--trait-link-color: #39afd7;
+	--assoc-item-link-color: #39afd7;
+	--function-link-color: #fdd687;
+	--macro-link-color: #a37acc;
+	--keyword-link-color: #39afd7;
+	--mod-link-color: #39afd7;
+	--link-color: #39afd7;
 }
 
 .slider {
@@ -111,44 +119,12 @@ pre, .rustdoc.source .example-wrap {
 
 .content .item-info::before { color: #ccc; }
 
-.content span.foreigntype, .content a.foreigntype { color: #ffa0a5; }
-.content span.union, .content a.union { color: #ffa0a5; }
-.content span.constant, .content a.constant,
-.content span.static, .content a.static { color: #39AFD7; }
-.content span.primitive, .content a.primitive { color: #ffa0a5; }
-.content span.traitalias, .content a.traitalias { color: #39AFD7; }
-.content span.keyword, .content a.keyword { color: #39AFD7; }
-.content span.mod, .content a.mod {
-	color: #39AFD7;
-}
-.content span.struct, .content a.struct {
-	color: #ffa0a5;
-}
-.content span.enum, .content a.enum {
-	color: #ffa0a5;
-}
-.content span.trait, .content a.trait {
-	color: #39AFD7;
-}
-.content span.type, .content a.type { color: #39AFD7; }
-.content span.associatedtype, .content a.associatedtype { color: #39AFD7; }
-.content span.fn, .content a.fn,
-.content .fnname { color: #fdd687; }
-.content span.attr, .content a.attr, .content span.derive,
-.content a.derive, .content span.macro, .content a.macro {
-	color: #a37acc;
-}
-
 .sidebar a { color: #53b1db; }
 .sidebar a.current.type { color: #53b1db; }
 
 pre.rust .comment { color: #788797; }
 pre.rust .doccomment { color: #a1ac88; }
 
-a {
-	color: #39AFD7;
-}
-
 .sidebar h2 a,
 .sidebar h3 a {
 	color: white;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 68542d3305c..07a1ed8b7db 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -22,6 +22,14 @@
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--type-link-color: #2dbfb8;
+	--trait-link-color: #b78cf2;
+	--assoc-item-link-color: #d2991d;
+	--function-link-color: #2bab63;
+	--macro-link-color: #09bd00;
+	--keyword-link-color: #d2991d;
+	--mod-link-color:  #d2991d;
+	--link-color: #d2991d;
 }
 
 .slider {
@@ -83,25 +91,6 @@ a.result-keyword:focus { background-color: #884719; }
 
 .content .item-info::before { color: #ccc; }
 
-.content span.enum, .content a.enum { color: #2dbfb8; }
-.content span.struct, .content a.struct { color: #2dbfb8; }
-.content span.type, .content a.type { color: #2dbfb8; }
-.content span.associatedtype, .content a.associatedtype { color: #D2991D; }
-.content span.foreigntype, .content a.foreigntype { color: #2dbfb8; }
-.content span.attr, .content a.attr,
-.content span.derive, .content a.derive,
-.content span.macro, .content a.macro { color: #09bd00; }
-.content span.union, .content a.union { color: #2dbfb8; }
-.content span.constant, .content a.constant,
-.content span.static, .content a.static { color: #D2991D; }
-.content span.primitive, .content a.primitive { color: #2dbfb8; }
-.content span.mod, .content a.mod { color: #D2991D; }
-.content span.trait, .content a.trait { color: #b78cf2; }
-.content span.traitalias, .content a.traitalias { color: #b78cf2; }
-.content span.fn, .content a.fn,
-.content .fnname { color: #2BAB63; }
-.content span.keyword, .content a.keyword { color: #D2991D; }
-
 .sidebar a { color: #fdbf35; }
 .sidebar a.current.enum { color: #12ece2; }
 .sidebar a.current.struct { color: #12ece2; }
@@ -122,10 +111,6 @@ a.result-keyword:focus { background-color: #884719; }
 pre.rust .comment { color: #8d8d8b; }
 pre.rust .doccomment { color: #8ca375; }
 
-a {
-	color: #D2991D;
-}
-
 body.source .example-wrap pre.rust a {
 	background: #333;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 0b7d1600e7a..64335f62928 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -22,6 +22,14 @@
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--type-link-color: #ad378a;
+	--trait-link-color: #6e4fc9;
+	--assoc-item-link-color: #3873ad;
+	--function-link-color: #ad7c37;
+	--macro-link-color: #068000;
+	--keyword-link-color: #3873ad;
+	--mod-link-color: #3873ad;
+	--link-color: #3873ad;
 }
 
 .slider {
@@ -82,25 +90,6 @@ a.result-keyword:focus { background-color: #afc6e4; }
 
 .content .item-info::before { color: #ccc; }
 
-.content span.enum, .content a.enum { color: #AD378A; }
-.content span.struct, .content a.struct { color: #AD378A; }
-.content span.type, .content a.type { color:  #AD378A; }
-.content span.associatedtype, .content a.associatedtype { color: #3873AD; }
-.content span.foreigntype, .content a.foreigntype { color: #3873AD; }
-.content span.attr, .content a.attr,
-.content span.derive, .content a.derive,
-.content span.macro, .content a.macro { color: #068000; }
-.content span.union, .content a.union { color: #AD378A; }
-.content span.constant, .content a.constant,
-.content span.static, .content a.static { color: #3873AD; }
-.content span.primitive, .content a.primitive { color: #AD378A; }
-.content span.mod, .content a.mod { color: #3873AD; }
-.content span.trait, .content a.trait { color: #6E4FC9; }
-.content span.traitalias, .content a.traitalias { color: #5137AD; }
-.content span.fn, .content a.fn,
-.content .fnname { color: #AD7C37; }
-.content span.keyword, .content a.keyword { color: #3873AD; }
-
 .sidebar a { color: #356da4; }
 .sidebar a.current.enum { color: #a63283; }
 .sidebar a.current.struct { color: #a63283; }
@@ -118,10 +107,6 @@ a.result-keyword:focus { background-color: #afc6e4; }
 .sidebar a.current.fn { color: #a67736; }
 .sidebar a.current.keyword { color: #356da4; }
 
-a {
-	color: #3873AD;
-}
-
 body.source .example-wrap pre.rust a {
 	background: #eee;
 }
diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml
new file mode 100644
index 00000000000..69c5b4a6733
--- /dev/null
+++ b/src/test/rustdoc-gui/links-color.goml
@@ -0,0 +1,85 @@
+// This test checks links colors.
+goto: file://|DOC_PATH|/test_docs/index.html
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {
+    "rustdoc-theme": "ayu",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+assert-css: (".item-table .mod", {"color": "rgb(57, 175, 215)"}, ALL)
+assert-css: (".item-table .macro", {"color": "rgb(163, 122, 204)"}, ALL)
+assert-css: (".item-table .struct", {"color": "rgb(255, 160, 165)"}, ALL)
+assert-css: (".item-table .enum", {"color": "rgb(255, 160, 165)"}, ALL)
+assert-css: (".item-table .trait", {"color": "rgb(57, 175, 215)"}, ALL)
+assert-css: (".item-table .fn", {"color": "rgb(253, 214, 135)"}, ALL)
+assert-css: (".item-table .type", {"color": "rgb(255, 160, 165)"}, ALL)
+assert-css: (".item-table .union", {"color": "rgb(255, 160, 165)"}, ALL)
+assert-css: (".item-table .keyword", {"color": "rgb(57, 175, 215)"}, ALL)
+
+assert-css: (
+    ".sidebar-elems a:not(.current)",
+    {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
+    ALL,
+)
+assert-css: (
+    ".sidebar-elems a.current",
+    {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "500"},
+    ALL,
+)
+
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark"}
+reload:
+
+assert-css: (".item-table .mod", {"color": "rgb(210, 153, 29)"}, ALL)
+assert-css: (".item-table .macro", {"color": "rgb(9, 189, 0)"}, ALL)
+assert-css: (".item-table .struct", {"color": "rgb(45, 191, 184)"}, ALL)
+assert-css: (".item-table .enum", {"color": "rgb(45, 191, 184)"}, ALL)
+assert-css: (".item-table .trait", {"color": "rgb(183, 140, 242)"}, ALL)
+assert-css: (".item-table .fn", {"color": "rgb(43, 171, 99)"}, ALL)
+assert-css: (".item-table .type", {"color": "rgb(45, 191, 184)"}, ALL)
+assert-css: (".item-table .union", {"color": "rgb(45, 191, 184)"}, ALL)
+assert-css: (".item-table .keyword", {"color": "rgb(210, 153, 29)"}, ALL)
+
+assert-css: (
+    ".sidebar-elems a:not(.current)",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
+    ALL,
+)
+assert-css: (
+    ".sidebar-elems a.current",
+    {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)", "font-weight": "500"},
+    ALL,
+)
+
+
+// Light theme
+local-storage: {"rustdoc-theme": "light"}
+reload:
+
+assert-css: (".item-table .mod", {"color": "rgb(56, 115, 173)"}, ALL)
+assert-css: (".item-table .macro", {"color": "rgb(6, 128, 0)"}, ALL)
+assert-css: (".item-table .struct", {"color": "rgb(173, 55, 138)"}, ALL)
+assert-css: (".item-table .enum", {"color": "rgb(173, 55, 138)"}, ALL)
+assert-css: (".item-table .trait", {"color": "rgb(110, 79, 201)"}, ALL)
+assert-css: (".item-table .fn", {"color": "rgb(173, 124, 55)"}, ALL)
+assert-css: (".item-table .type", {"color": "rgb(173, 55, 138)"}, ALL)
+assert-css: (".item-table .union", {"color": "rgb(173, 55, 138)"}, ALL)
+assert-css: (".item-table .keyword", {"color": "rgb(56, 115, 173)"}, ALL)
+
+assert-css: (
+    ".sidebar-elems a:not(.current)",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"},
+    ALL,
+)
+assert-css: (
+    ".sidebar-elems a.current",
+    {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)", "font-weight": "500"},
+    ALL,
+)
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
index 07c8c9ff254..003542d3855 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
@@ -70,3 +70,13 @@ pub struct NestedGenericsWithPunct;
 //~^ ERROR unclosed HTML tag `i32`
 //~|HELP try marking as source
 pub struct NestedGenericsWithPunct2;
+
+/// This [`Vec<i32>`] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLink;
+
+/// This [`Vec::<i32>`] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLinkTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.rs b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
index cdd652f397e..4254a660b19 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.rs
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
@@ -70,3 +70,13 @@ pub struct NestedGenericsWithPunct;
 //~^ ERROR unclosed HTML tag `i32`
 //~|HELP try marking as source
 pub struct NestedGenericsWithPunct2;
+
+/// This [Vec<i32>] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLink;
+
+/// This [Vec::<i32>] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLinkTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
index 211dd4210d5..481278bdaf9 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
@@ -157,5 +157,27 @@ help: try marking as source code
 LL | /// Generics with punct `Vec<Vec<i32>>`!
    |                         +             +
 
-error: aborting due to 14 previous errors
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:74:14
+   |
+LL | /// This [Vec<i32>] thing!
+   |              ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This [`Vec<i32>`] thing!
+   |           +        +
+
+error: unclosed HTML tag `i32`
+  --> $DIR/html-as-generics.rs:79:16
+   |
+LL | /// This [Vec::<i32>] thing!
+   |                ^^^^^
+   |
+help: try marking as source code
+   |
+LL | /// This [`Vec::<i32>`] thing!
+   |           +          +
+
+error: aborting due to 16 previous errors
 
diff --git a/src/test/rustdoc/index-page.rs b/src/test/rustdoc/index-page.rs
index be668a1276a..5677019fbb8 100644
--- a/src/test/rustdoc/index-page.rs
+++ b/src/test/rustdoc/index-page.rs
@@ -6,6 +6,6 @@
 
 // @has foo/../index.html
 // @has - '//span[@class="in-band"]' 'List of all crates'
-// @has - '//ul[@class="crate mod"]//a[@href="foo/index.html"]' 'foo'
-// @has - '//ul[@class="crate mod"]//a[@href="all_item_types/index.html"]' 'all_item_types'
+// @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo'
+// @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types'
 pub struct Foo;
diff --git a/src/test/ui/query-system/query_depth.rs b/src/test/ui/query-system/query_depth.rs
new file mode 100644
index 00000000000..e600c1c08e5
--- /dev/null
+++ b/src/test/ui/query-system/query_depth.rs
@@ -0,0 +1,31 @@
+// build-fail
+
+#![recursion_limit = "64"]
+type Byte = Option<Option<Option<Option< Option<Option<Option<Option<
+    Option<Option<Option<Option< Option<Option<Option<Option<
+        Option<Option<Option<Option< Option<Option<Option<Option<
+            Option<Option<Option<Option< Option<Option<Option<Option<
+                Option<Option<Option<Option< Option<Option<Option<Option<
+                    Option<Option<Option<Option< Option<Option<Option<Option<
+                        Option<Option<Option<Option< Option<Option<Option<Option<
+                            Option<Option<Option<Option< Option<Option<Option<Option<
+                                Option<Option<Option<Option< Option<Option<Option<Option<
+                                    Option<Option<Option<Option< Option<Option<Option<Option<
+                                        Option<Option<Option<Option< Option<Option<Option<Option<
+                                            Box<String>
+                                        >>>> >>>>
+                                    >>>> >>>>
+                                >>>> >>>>
+                            >>>> >>>>
+                        >>>> >>>>
+                    >>>> >>>>
+                >>>> >>>>
+            >>>> >>>>
+        >>>> >>>>
+    >>>> >>>>
+>>>> >>>>;
+
+fn main() {
+//~^ ERROR: queries overflow the depth limit!
+    println!("{}", std::mem::size_of::<Byte>());
+}
diff --git a/src/test/ui/query-system/query_depth.stderr b/src/test/ui/query-system/query_depth.stderr
new file mode 100644
index 00000000000..43a18b4e074
--- /dev/null
+++ b/src/test/ui/query-system/query_depth.stderr
@@ -0,0 +1,11 @@
+error: queries overflow the depth limit!
+  --> $DIR/query_depth.rs:28:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`)
+   = note: query depth increased by 66 when computing layout of `core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<alloc::boxed::Box<alloc::string::String>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+
+error: aborting due to previous error
+