about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/bootstrap.py53
-rw-r--r--src/bootstrap/builder.rs10
-rw-r--r--src/bootstrap/compile.rs5
-rw-r--r--src/bootstrap/dist.rs21
-rw-r--r--src/bootstrap/lib.rs14
-rw-r--r--src/bootstrap/native.rs71
-rw-r--r--src/bootstrap/util.rs18
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh15
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/pgo.sh6
-rwxr-xr-xsrc/ci/scripts/upload-artifacts.sh3
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/command-line-arguments.md3
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/pc-windows-gnullvm.md48
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md17
-rw-r--r--src/doc/rustdoc/src/write-documentation/what-to-include.md5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md5
-rw-r--r--src/librustdoc/Cargo.toml4
-rw-r--r--src/librustdoc/clean/blanket_impl.rs18
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/docfs.rs7
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/librustdoc/html/render/context.rs16
-rw-r--r--src/librustdoc/html/render/write_shared.rs11
-rw-r--r--src/librustdoc/html/static/.eslintrc.js5
-rw-r--r--src/librustdoc/html/static/css/noscript.css4
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css58
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css23
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css20
-rw-r--r--src/librustdoc/html/static/css/themes/light.css21
-rw-r--r--src/librustdoc/html/static/js/main.js141
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js4
-rw-r--r--src/librustdoc/html/static/js/search.js187
-rw-r--r--src/librustdoc/html/static/js/settings.js76
-rw-r--r--src/librustdoc/html/static/js/storage.js5
-rw-r--r--src/librustdoc/html/static_files.rs3
-rw-r--r--src/librustdoc/html/templates/page.html15
-rw-r--r--src/librustdoc/json/conversions.rs10
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs770
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs65
-rw-r--r--src/librustdoc/scrape_examples.rs2
-rw-r--r--src/rustdoc-json-types/lib.rs25
-rw-r--r--src/test/codegen/asm-clobber_abi.rs8
-rw-r--r--src/test/codegen/asm-target-clobbers.rs7
-rw-r--r--src/test/codegen/remap_path_prefix/main.rs2
-rw-r--r--src/test/codegen/simd-wide-sum.rs54
-rw-r--r--src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs21
-rw-r--r--src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir24
-rw-r--r--src/test/mir-opt/asm_unwind_panic_abort.rs16
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/driver.rs60
-rw-r--r--src/test/run-make/remap-path-prefix-dwarf/Makefile77
-rw-r--r--src/test/run-make/remap-path-prefix-dwarf/src/quux.rs5
-rw-r--r--src/test/rustdoc-gui/search-filter.goml34
-rw-r--r--src/test/rustdoc-gui/settings.goml23
-rw-r--r--src/test/rustdoc-gui/shortcuts.goml12
-rw-r--r--src/test/rustdoc-gui/theme-change.goml19
-rw-r--r--src/test/rustdoc-json/fn_pointer/generics.rs14
-rw-r--r--src/test/rustdoc-json/fns/generic_args.rs32
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules-error.rs11
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr23
-rw-r--r--src/test/ui/asm/generic-const.rs30
-rw-r--r--src/test/ui/asm/type-check-1.rs1
-rw-r--r--src/test/ui/asm/type-check-1.stderr15
-rw-r--r--src/test/ui/associated-types/hr-associated-type-projection-1.stderr14
-rw-r--r--src/test/ui/async-await/issue-73741-type-err-drop-tracking.rs14
-rw-r--r--src/test/ui/async-await/issue-73741-type-err-drop-tracking.stderr11
-rw-r--r--src/test/ui/binop/issue-77910-1.stderr14
-rw-r--r--src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr7
-rw-r--r--src/test/ui/coherence/coherence-with-closure.rs15
-rw-r--r--src/test/ui/coherence/coherence-with-closure.stderr24
-rw-r--r--src/test/ui/coherence/coherence-with-generator.rs19
-rw-r--r--src/test/ui/coherence/coherence-with-generator.stderr24
-rw-r--r--src/test/ui/const-generics/issues/issue-88119.rs35
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr2
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr2
-rw-r--r--src/test/ui/consts/const-fn-ptr.rs16
-rw-r--r--src/test/ui/consts/const-fn-ptr.stderr20
-rw-r--r--src/test/ui/consts/issue-56164.stderr2
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.stderr2
-rw-r--r--src/test/ui/consts/validate_never_arrays.32bit.stderr2
-rw-r--r--src/test/ui/consts/validate_never_arrays.64bit.stderr2
-rw-r--r--src/test/ui/empty/empty-linkname.rs2
-rw-r--r--src/test/ui/empty/empty-linkname.stderr6
-rw-r--r--src/test/ui/error-codes/E0138.stderr4
-rw-r--r--src/test/ui/error-codes/E0454.stderr6
-rw-r--r--src/test/ui/error-codes/E0458.stderr10
-rw-r--r--src/test/ui/error-codes/E0459.stderr2
-rw-r--r--src/test/ui/error-codes/E0604.stderr9
-rw-r--r--src/test/ui/error-festival.stderr9
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_const.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_const.stderr13
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_sym.rs11
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_sym.stderr17
-rw-r--r--src/test/ui/feature-gates/feature-gate-link_cfg.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib.stderr6
-rw-r--r--src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-static-nobundle.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-static-nobundle.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr3
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs4
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr128
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs17
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs31
-rw-r--r--src/test/ui/impl-trait/issues/issue-54895.rs3
-rw-r--r--src/test/ui/impl-trait/issues/issue-54895.stderr14
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.nll.stderr20
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-67830.stderr13
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr55
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.rs9
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236-2.stderr40
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.rs3
-rw-r--r--src/test/ui/impl-trait/issues/issue-88236.stderr14
-rw-r--r--src/test/ui/impl-trait/nested-rpit-hrtb.rs64
-rw-r--r--src/test/ui/impl-trait/nested-rpit-hrtb.stderr82
-rw-r--r--src/test/ui/imports/unused-imports-in-test-mode.rs84
-rw-r--r--src/test/ui/imports/unused-imports-in-test-mode.stderr122
-rw-r--r--src/test/ui/inference/issue-28935.rs9
-rw-r--r--src/test/ui/inline-const/const-match-pat-generic.rs3
-rw-r--r--src/test/ui/inline-const/const-match-pat-generic.stderr15
-rw-r--r--src/test/ui/issues/issue-11515.stderr3
-rw-r--r--src/test/ui/issues/issue-43925.rs2
-rw-r--r--src/test/ui/issues/issue-43925.stderr6
-rw-r--r--src/test/ui/issues/issue-43926.rs2
-rw-r--r--src/test/ui/issues/issue-43926.stderr2
-rw-r--r--src/test/ui/issues/issue-5239-1.stderr5
-rw-r--r--src/test/ui/linkage-attr/bad-extern-link-attrs.rs7
-rw-r--r--src/test/ui/linkage-attr/bad-extern-link-attrs.stderr24
-rw-r--r--src/test/ui/linkage-attr/link-attr-validation-early.rs8
-rw-r--r--src/test/ui/linkage-attr/link-attr-validation-early.stderr21
-rw-r--r--src/test/ui/linkage-attr/link-attr-validation-late.rs40
-rw-r--r--src/test/ui/linkage-attr/link-attr-validation-late.stderr147
-rw-r--r--src/test/ui/main-wrong-location.stderr2
-rw-r--r--src/test/ui/manual/manual-link-bad-form.rs2
-rw-r--r--src/test/ui/manual/manual-link-bad-form.stderr4
-rw-r--r--src/test/ui/manual/manual-link-bad-kind.rs2
-rw-r--r--src/test/ui/manual/manual-link-bad-kind.stderr2
-rw-r--r--src/test/ui/manual/manual-link-framework.rs2
-rw-r--r--src/test/ui/manual/manual-link-framework.stderr2
-rw-r--r--src/test/ui/manual/manual-link-unsupported-kind.rs2
-rw-r--r--src/test/ui/manual/manual-link-unsupported-kind.stderr2
-rw-r--r--src/test/ui/mismatched_types/cast-rfc0401.stderr9
-rw-r--r--src/test/ui/native-library-link-flags/empty-kind-1.rs2
-rw-r--r--src/test/ui/native-library-link-flags/empty-kind-1.stderr2
-rw-r--r--src/test/ui/native-library-link-flags/empty-kind-2.rs2
-rw-r--r--src/test/ui/native-library-link-flags/empty-kind-2.stderr2
-rw-r--r--src/test/ui/native-library-link-flags/modifiers-override-2.stderr2
-rw-r--r--src/test/ui/native-library-link-flags/modifiers-override.rs5
-rw-r--r--src/test/ui/native-library-link-flags/modifiers-override.stderr26
-rw-r--r--src/test/ui/nll/issue-54779-anon-static-lifetime.rs51
-rw-r--r--src/test/ui/nll/issue-54779-anon-static-lifetime.stderr11
-rw-r--r--src/test/ui/osx-frameworks.rs2
-rw-r--r--src/test/ui/osx-frameworks.stderr6
-rw-r--r--src/test/ui/parser/issue-81804.rs9
-rw-r--r--src/test/ui/parser/issue-81804.stderr41
-rw-r--r--src/test/ui/privacy/auxiliary/ctor_aux.rs25
-rw-r--r--src/test/ui/privacy/ctor.rs16
-rw-r--r--src/test/ui/rfc-1717-dllimport/rename-modifiers.rs9
-rw-r--r--src/test/ui/rfc-1717-dllimport/rename-modifiers.stderr8
-rw-r--r--src/test/ui/rfc-2294-if-let-guard/typeck.stderr8
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs2
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr7
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr1
-rw-r--r--src/test/ui/suggestions/mut-ref-reassignment.stderr4
-rw-r--r--src/test/ui/traits/assoc-type-in-superbad.stderr8
-rw-r--r--src/test/ui/typeck/assign-non-lval-derefmut.fixed15
-rw-r--r--src/test/ui/typeck/assign-non-lval-derefmut.rs15
-rw-r--r--src/test/ui/typeck/assign-non-lval-derefmut.stderr58
-rw-r--r--src/test/ui/typeck/assign-non-lval-mut-ref.fixed15
-rw-r--r--src/test/ui/typeck/assign-non-lval-mut-ref.rs15
-rw-r--r--src/test/ui/typeck/assign-non-lval-mut-ref.stderr56
-rw-r--r--src/test/ui/typeck/issue-93486.stderr5
-rw-r--r--src/test/ui/wasm/wasm-import-module.rs11
-rw-r--r--src/test/ui/wasm/wasm-import-module.stderr32
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_match.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs58
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs2
m---------src/tools/miri14
-rw-r--r--src/tools/rustdoc-gui/tester.js2
-rw-r--r--src/tools/rustdoc-js/tester.js305
-rw-r--r--src/tools/rustfmt/src/macros.rs4
-rw-r--r--src/version2
204 files changed, 2828 insertions, 1775 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index ab4338e1c85..d36344ece4e 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -110,29 +110,42 @@ def download(path, url, probably_big, verbose, help_on_error=None):
 
 
 def _download(path, url, probably_big, verbose, exception, help_on_error=None):
+    # Try to use curl (potentially available on win32
+    #    https://devblogs.microsoft.com/commandline/tar-and-curl-come-to-windows/)
+    # If an error occurs:
+    #  - If we are on win32 fallback to powershell
+    #  - Otherwise raise the error if appropriate
     if probably_big or verbose:
         print("downloading {}".format(url))
-    # see https://serverfault.com/questions/301128/how-to-download
-    if sys.platform == 'win32':
-        run(["PowerShell.exe", "/nologo", "-Command",
-             "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
-             "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
-            verbose=verbose,
-            exception=exception)
-    else:
+
+    platform_is_win32 = sys.platform == 'win32'
+    try:
         if probably_big or verbose:
             option = "-#"
         else:
             option = "-s"
-        require(["curl", "--version"])
+        # If curl is not present on Win32, we shoud not sys.exit
+        #   but raise `CalledProcessError` or `OSError` instead
+        require(["curl", "--version"], exception=platform_is_win32)
         run(["curl", option,
              "-L", # Follow redirect.
              "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
              "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
              "--retry", "3", "-Sf", "-o", path, url],
             verbose=verbose,
-            exception=exception,
+            exception=True, # Will raise RuntimeError on failure
             help_on_error=help_on_error)
+    except (subprocess.CalledProcessError, OSError, RuntimeError):
+        # see http://serverfault.com/questions/301128/how-to-download
+        if platform_is_win32:
+            run(["PowerShell.exe", "/nologo", "-Command",
+                 "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
+                 "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
+                verbose=verbose,
+                exception=exception)
+        # Check if the RuntimeError raised by run(curl) should be silenced
+        elif verbose or exception:
+            raise
 
 
 def verify(path, expected, verbose):
@@ -198,19 +211,23 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, help_on_error=
             sys.exit(err)
 
 
-def require(cmd, exit=True):
+def require(cmd, exit=True, exception=False):
     '''Run a command, returning its output.
     On error,
-        If `exit` is `True`, exit the process.
-        Otherwise, return None.'''
+        If `exception` is `True`, raise the error
+        Otherwise If `exit` is `True`, exit the process
+        Else return None.'''
     try:
         return subprocess.check_output(cmd).strip()
     except (subprocess.CalledProcessError, OSError) as exc:
-        if not exit:
-            return None
-        print("error: unable to run `{}`: {}".format(' '.join(cmd), exc))
-        print("Please make sure it's installed and in the path.")
-        sys.exit(1)
+        if exception:
+            raise
+        elif exit:
+            print("error: unable to run `{}`: {}".format(' '.join(cmd), exc))
+            print("Please make sure it's installed and in the path.")
+            sys.exit(1)
+        return None
+
 
 
 def format_build_time(duration):
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 7d838c0a61d..894d74fb269 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1154,9 +1154,13 @@ impl<'a> Builder<'a> {
             // backtrace, core_simd, std_float, ...), those dependencies have their own features
             // but cargo isn't involved in the #[path] and so cannot pass the complete list of
             // features, so for that reason we don't enable checking of features for std.
-            if mode != Mode::Std {
-                cargo.arg("-Zcheck-cfg-features");
-            }
+            //
+            // FIXME: Re-enable this after the beta bump as apperently rustc-perf doesn't use the
+            // beta cargo. See https://github.com/rust-lang/rust/pull/96984#issuecomment-1126678773
+            // #[cfg(not(bootstrap))]
+            // if mode != Mode::Std {
+            //     cargo.arg("-Zcheck-cfg-features"); // -Zcheck-cfg=features after bump
+            // }
 
             // Enable cfg checking of well known names/values
             rustflags
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 53933e4cd7d..7a8c7fee5f5 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -175,6 +175,7 @@ fn copy_third_party_objects(
     }
 
     if target == "x86_64-fortanix-unknown-sgx"
+        || target.contains("pc-windows-gnullvm")
         || builder.config.llvm_libunwind == LlvmLibunwind::InTree
             && (target.contains("linux") || target.contains("fuchsia"))
     {
@@ -246,7 +247,7 @@ fn copy_self_contained_objects(
                 DependencyType::TargetSelfContained,
             );
         }
-    } else if target.contains("windows-gnu") {
+    } else if target.ends_with("windows-gnu") {
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
             let src = compiler_file(builder, builder.cc(target), target, CLang::C, obj);
             let target = libdir_self_contained.join(obj);
@@ -477,7 +478,7 @@ impl Step for StartupObjects {
     fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
         let for_compiler = self.compiler;
         let target = self.target;
-        if !target.contains("windows-gnu") {
+        if !target.ends_with("windows-gnu") {
             return vec![];
         }
 
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index d37a59426f8..16727f4398d 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -285,7 +285,7 @@ impl Step for Mingw {
     /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        if !host.contains("pc-windows-gnu") {
+        if !host.ends_with("pc-windows-gnu") {
             return None;
         }
 
@@ -341,7 +341,7 @@ impl Step for Rustc {
         // anything requiring us to distribute a license, but it's likely the
         // install will *also* include the rust-mingw package, which also needs
         // licenses, so to be safe we just include it here in all MinGW packages.
-        if host.contains("pc-windows-gnu") {
+        if host.ends_with("pc-windows-gnu") {
             make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder);
             tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
         }
@@ -1352,7 +1352,7 @@ impl Step for Extended {
         tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
         tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
 
-        if target.contains("windows-gnu") {
+        if target.ends_with("windows-gnu") {
             tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
         }
 
@@ -1522,7 +1522,7 @@ impl Step for Extended {
                     prepare(tool);
                 }
             }
-            if target.contains("windows-gnu") {
+            if target.ends_with("windows-gnu") {
                 prepare("rust-mingw");
             }
 
@@ -1711,7 +1711,7 @@ impl Step for Extended {
                     .arg("-t")
                     .arg(etc.join("msi/remove-duplicates.xsl")),
             );
-            if target.contains("windows-gnu") {
+            if target.ends_with("windows-gnu") {
                 builder.run(
                     Command::new(&heat)
                         .current_dir(&exe)
@@ -1760,7 +1760,7 @@ impl Step for Extended {
                 if built_tools.contains("miri") {
                     cmd.arg("-dMiriDir=miri");
                 }
-                if target.contains("windows-gnu") {
+                if target.ends_with("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
                 builder.run(&mut cmd);
@@ -1787,7 +1787,7 @@ impl Step for Extended {
             }
             candle("AnalysisGroup.wxs".as_ref());
 
-            if target.contains("windows-gnu") {
+            if target.ends_with("windows-gnu") {
                 candle("GccGroup.wxs".as_ref());
             }
 
@@ -1829,7 +1829,7 @@ impl Step for Extended {
                 cmd.arg("MiriGroup.wixobj");
             }
 
-            if target.contains("windows-gnu") {
+            if target.ends_with("windows-gnu") {
                 cmd.arg("GccGroup.wixobj");
             }
             // ICE57 wrongly complains about the shortcuts
@@ -1859,7 +1859,9 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
         .env("CFG_BUILD", target.triple)
         .env("CFG_CHANNEL", &builder.config.channel);
 
-    if target.contains("windows-gnu") {
+    if target.contains("windows-gnullvm") {
+        cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
+    } else if target.contains("windows-gnu") {
         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
     } else {
         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
@@ -2045,6 +2047,7 @@ impl Step for RustDev {
             "llvm-cov",
             "llvm-dwp",
             "llvm-nm",
+            "llvm-dwarfdump",
         ] {
             tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
         }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 5d32b4f801a..a4e35bf6d47 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -122,7 +122,8 @@ use once_cell::sync::OnceCell;
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
 use crate::util::{
-    exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed, CiEnv,
+    check_run, exe, libdir, mtime, output, run, run_suppressed, t, try_run, try_run_suppressed,
+    CiEnv,
 };
 
 mod builder;
@@ -961,6 +962,17 @@ impl Build {
         try_run_suppressed(cmd)
     }
 
+    /// Runs a command, printing out nice contextual information if it fails.
+    /// Returns false if do not execute at all, otherwise returns its
+    /// `status.success()`.
+    fn check_run(&self, cmd: &mut Command) -> bool {
+        if self.config.dry_run {
+            return true;
+        }
+        self.verbose(&format!("running: {:?}", cmd));
+        check_run(cmd, self.is_verbose())
+    }
+
     pub fn is_verbose(&self) -> bool {
         self.verbosity > 0
     }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 64e25f803b2..09b8cbe9014 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -156,7 +156,7 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
         let llvm_lib = llvm_root.join("lib");
         for entry in t!(fs::read_dir(&llvm_lib)) {
             let lib = t!(entry).path();
-            if lib.ends_with(".so") {
+            if lib.extension().map_or(false, |ext| ext == "so") {
                 fix_bin_or_dylib(builder, &lib);
             }
         }
@@ -284,7 +284,7 @@ fn fix_bin_or_dylib(builder: &Builder<'_>, fname: &Path) {
         entries
     };
     patchelf.args(&[OsString::from("--set-rpath"), rpath_entries]);
-    if !fname.ends_with(".so") {
+    if !fname.extension().map_or(false, |ext| ext == "so") {
         // Finally, set the corret .interp for binaries
         let dynamic_linker_path = nix_deps_dir.join("nix-support/dynamic-linker");
         // FIXME: can we support utf8 here? `args` doesn't accept Vec<u8>, only OsString ...
@@ -306,39 +306,40 @@ fn download_component(builder: &Builder<'_>, base: &str, url: &str, dest_path: &
 
 fn download_with_retries(builder: &Builder<'_>, tempfile: &str, url: &str) {
     println!("downloading {}", url);
-
-    // FIXME: check if curl is installed instead of skipping straight to powershell
-    if builder.build.build.contains("windows-msvc") {
-        for _ in 0..3 {
-            if builder.try_run(Command::new("PowerShell.exe").args(&[
-                "/nologo",
-                "-Command",
-                "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
-                &format!(
-                    "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
-                    url, tempfile
-                ),
-            ])) {
-                return;
+    // Try curl. If that fails and we are on windows, fallback to PowerShell.
+    if !builder.check_run(Command::new("curl").args(&[
+        "-#",
+        "-y",
+        "30",
+        "-Y",
+        "10", // timeout if speed is < 10 bytes/sec for > 30 seconds
+        "--connect-timeout",
+        "30", // timeout if cannot connect within 30 seconds
+        "--retry",
+        "3",
+        "-Sf",
+        "-o",
+        tempfile,
+        url,
+    ])) {
+        if builder.build.build.contains("windows-msvc") {
+            println!("Fallback to PowerShell");
+            for _ in 0..3 {
+                if builder.try_run(Command::new("PowerShell.exe").args(&[
+                    "/nologo",
+                    "-Command",
+                    "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
+                    &format!(
+                        "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
+                        url, tempfile
+                    ),
+                ])) {
+                    return;
+                }
+                println!("\nspurious failure, trying again");
             }
-            println!("\nspurious failure, trying again");
         }
-    } else {
-        builder.run(Command::new("curl").args(&[
-            "-#",
-            "-y",
-            "30",
-            "-Y",
-            "10", // timeout if speed is < 10 bytes/sec for > 30 seconds
-            "--connect-timeout",
-            "30", // timeout if cannot connect within 30 seconds
-            "--retry",
-            "3",
-            "-Sf",
-            "-o",
-            tempfile,
-            url,
-        ]));
+        std::process::exit(1);
     }
 }
 
@@ -1372,6 +1373,10 @@ impl Step for Libunwind {
                 cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
                 cfg.define("NDEBUG", None);
             }
+            if self.target.contains("windows") {
+                cfg.define("_LIBUNWIND_HIDE_SYMBOLS", "1");
+                cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
+            }
         }
 
         cc_cfg.compiler(builder.cc(self.target));
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index b78ca3712bd..710b3588b84 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -346,6 +346,24 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
     status.success()
 }
 
+pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
+    let status = match cmd.status() {
+        Ok(status) => status,
+        Err(e) => {
+            println!("failed to execute command: {:?}\nerror: {}", cmd, e);
+            return false;
+        }
+    };
+    if !status.success() && print_cmd_on_fail {
+        println!(
+            "\n\ncommand did not execute successfully: {:?}\n\
+             expected success, got: {}\n\n",
+            cmd, status
+        );
+    }
+    status.success()
+}
+
 pub fn run_suppressed(cmd: &mut Command) {
     if !try_run_suppressed(cmd) {
         std::process::exit(1);
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index 9bd56394eaf..36c94458da7 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -2,16 +2,21 @@
 
 set -ex
 
-# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/clang+llvm-11.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
-curl https://ci-mirrors.rust-lang.org/rustc/2021-01-14-clang%2Bllvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz | \
+# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
+curl https://ci-mirrors.rust-lang.org/rustc/2022-05-10-clang%2Bllvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
   tar xJf -
-export PATH=`pwd`/clang+llvm-11.0.1-x86_64-linux-gnu-ubuntu-16.04/bin:$PATH
+bin="$PWD/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04/bin"
 
 git clone https://github.com/WebAssembly/wasi-libc
 
 cd wasi-libc
-git reset --hard ad5133410f66b93a2381db5b542aad5e0964db96
-make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
+git reset --hard 9886d3d6200fcc3726329966860fc058707406cd
+make -j$(nproc) \
+    CC="$bin/clang" \
+    NM="$bin/llvm-nm" \
+    AR="$bin/llvm-ar" \
+    INSTALL_DIR=/wasm32-wasi \
+    install
 
 cd ..
 rm -rf wasi-libc
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 899f24fc754..b3ec1638fda 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.9.0
\ No newline at end of file
+0.9.3
\ No newline at end of file
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
index 691d1282cf4..aedfe98bdea 100755
--- a/src/ci/pgo.sh
+++ b/src/ci/pgo.sh
@@ -82,7 +82,11 @@ python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
 
 # Here we're profiling the `rustc` frontend, so we also include `Check`.
 # The benchmark set includes various stress tests that put the frontend under pressure.
-gather_profiles "Check,Debug,Opt" "All" \
+# The profile data is written into a single filepath that is being repeatedly merged when each
+# rustc invocation ends. Empirically, this can result in some profiling data being lost.
+# That's why we override the profile path to include the PID. This will produce many more profiling
+# files, but the resulting profile will produce a slightly faster rustc binary.
+LLVM_PROFILE_FILE=/tmp/rustc-pgo/default_%m_%p.profraw gather_profiles "Check,Debug,Opt" "All" \
   "externs,ctfe-stress-4,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress"
 
 # Merge the profile data we gathered
diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh
index 312ec9d8050..cea9b770f2a 100755
--- a/src/ci/scripts/upload-artifacts.sh
+++ b/src/ci/scripts/upload-artifacts.sh
@@ -38,4 +38,5 @@ if [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then
 fi
 deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)"
 
-retry aws s3 cp --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}"
+retry aws s3 cp --storage-class INTELLIGENT_TIERING \
+    --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}"
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index df95325c83d..c2d44ac0e4d 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -21,6 +21,7 @@
     - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
     - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
     - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
+    - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [*-unknown-openbsd](platform-support/openbsd.md)
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 0d02fa7bd6b..d80e4f20869 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -52,7 +52,8 @@ where `KIND` may be one of:
 If the kind is specified, then linking modifiers can be attached to it.
 Modifiers are specified as a comma-delimited string with each modifier prefixed with
 either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively.
-The last boolean value specified for a given modifier wins. \
+Specifying multiple `modifiers` arguments in a single `link` attribute,
+or multiple identical modifiers in the same `modifiers` argument is not currently supported. \
 Example: `-l static:+whole-archive=mylib`.
 
 The kind of library and the modifiers can also be specified in a [`#[link]`
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 12ac575210a..ab98651a1ec 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -208,6 +208,7 @@ target | std | host | notes
 `aarch64-apple-ios-macabi` | ? |  | Apple Catalyst on ARM64
 `aarch64-apple-tvos` | * |  | ARM64 tvOS
 [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ |  | ARM64 SOLID with TOPPERS/ASP3
+[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ✓ |  | ARM64 HermitCore
 `aarch64-unknown-uefi` | * |  | ARM64 UEFI
@@ -288,6 +289,7 @@ target | std | host | notes
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
+[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `x86_64-pc-windows-msvc` | * |  | 64-bit Windows XP support
 `x86_64-sun-solaris` | ? |  | Deprecated target for 64-bit Solaris 10/11, illumos
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
diff --git a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md
new file mode 100644
index 00000000000..96ae065b31b
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md
@@ -0,0 +1,48 @@
+# \*-pc-windows-gnullvm
+
+**Tier: 3**
+
+Windows targets similar to `*-pc-windows-gnu` but using UCRT as the runtime and various LLVM tools/libraries instead of GCC/Binutils.
+
+Target triples avaiable so far:
+- `aarch64-pc-windows-gnullvm`
+- `x86_64-pc-windows-gnullvm`
+
+## Target maintainers
+
+- [@mati865](https://github.com/mati865)
+
+## Requirements
+
+The easiest way to obtain these targets is cross-compilation but native build from `x86_64-pc-windows-gnu` is possible with few hacks which I don't recommend.
+Std support is expected to be on pair with `*-pc-windows-gnu`.
+
+Binaries for this target should be at least on pair with `*-pc-windows-gnu` in terms of requirements and functionality.
+
+Those targets follow Windows calling convention for `extern "C"`.
+
+Like with any other Windows target created binaries are in PE format.
+
+## Building the target
+
+For cross-compilation I recommend using [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain, one change that seems necessary beside configuring corss compilers is disabling experimental `m86k` target. Otherwise LLVM build fails with `multiple definition ...` errors.
+Native bootstrapping builds require rather fragile hacks until host artifacts are avaiable so I won't describe them here.
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+Created binaries work fine on Windows or Wine using native hardware. Testing AArch64 on x86_64 is problematic though and requires spending some time with QEMU.
+Once these targets bootstrap themselves on native hardware they should pass Rust testsuite.
+
+## Cross-compilation toolchains and C code
+
+Compatible C code can be built with Clang's `aarch64-pc-windows-gnu` and `x86_64-pc-windows-gnu` targets as long as LLVM based C toolchains are used.
+Those include:
+- [llvm-mingw](https://github.com/mstorsjo/llvm-mingw)
+- [MSYS2 with CLANG* environment](https://www.msys2.org/docs/environments)
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
index 098bc1879b5..d666d54b315 100644
--- a/src/doc/rustdoc/src/how-to-read-rustdoc.md
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -59,15 +59,8 @@ or the current item whose documentation is being displayed.
 ## The Theme Picker and Search Interface
 
 When viewing `rustdoc`'s output in a browser with JavaScript enabled,
-a dynamic interface appears at the top of the page.
-To the left is the theme picker, denoted with a paint-brush icon,
-and the search interface, help screen, and options appear to the right of that.
-
-### The Theme Picker
-
-Clicking on the theme picker provides a list of themes -
-by default `ayu`, `light`, and `dark` -
-which are available for viewing.
+a dynamic interface appears at the top of the page composed of the search
+interface, help screen, and options.
 
 ### The Search Interface
 
@@ -91,12 +84,16 @@ When typing in the search bar, you can prefix your search term with a type
 followed by a colon (such as `mod:`) to restrict the results to just that
 kind of item. (The available items are listed in the help popup.)
 
+### Changing displayed theme
+
+You can change the displayed theme by opening the settings menu (the gear
+icon in the upper right) and then pick a new one from there.
+
 ### Shortcuts
 
 Pressing `S` while focused elsewhere on the page will move focus to the
 search bar, and pressing `?` shows the help screen,
 which includes all these shortcuts and more.
-Pressing `T` focuses the theme picker.
 
 When the search results are focused,
 the left and right arrows move between tabs and the up and down arrows move
diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md
index 35e6ccbc388..e1e09aa4a8a 100644
--- a/src/doc/rustdoc/src/write-documentation/what-to-include.md
+++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md
@@ -109,8 +109,9 @@ rustdoc --extend-css custom.css src/lib.rs
 
 A good example of using this feature to create a dark theme is documented [on
 this blog].  Just remember, dark theme is already included in the rustdoc output
-by clicking on the paintbrush.  Adding additional options to the themes are
-as easy as creating a custom theme `.css` file and using the following syntax:
+by clicking on the gear icon in the upper right. Adding additional options to the
+themes are as easy as creating a custom theme `.css` file and using the following
+syntax:
 
 ```bash
 rustdoc --theme awesome.css src/lib.rs
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 3f60caffef5..e83c4d98cc7 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -22,7 +22,10 @@ This feature allows for use of one of following sanitizers:
 
 To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
 `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
-`-Zsanitizer=memtag`, or `-Zsanitizer=thread`.
+`-Zsanitizer=memtag`, or `-Zsanitizer=thread`. You might also need the `--target` and `build-std` flags. Example:
+```shell
+$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
+```
 
 # AddressSanitizer
 
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 21efd040663..0495cd97dc2 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -12,7 +12,6 @@ askama = { version = "0.11", default-features = false, features = ["config"] }
 atty = "0.2"
 pulldown-cmark = { version = "0.9", default-features = false }
 minifier = "0.0.43"
-rayon = "1.5.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 smallvec = "1.6.1"
@@ -29,6 +28,9 @@ version = "0.3.3"
 default-features = false
 features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"]
 
+[target.'cfg(windows)'.dependencies]
+rayon = "1.5.1"
+
 [dev-dependencies]
 expect-test = "1.0"
 
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index f0d87f7ce4c..805cc5c71d8 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -15,14 +15,14 @@ crate struct BlanketImplFinder<'a, 'tcx> {
 impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
     crate fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
         let param_env = self.cx.tcx.param_env(item_def_id);
-        let ty = self.cx.tcx.type_of(item_def_id);
+        let ty = self.cx.tcx.bound_type_of(item_def_id);
 
         trace!("get_blanket_impls({:?})", ty);
         let mut impls = Vec::new();
         self.cx.with_all_traits(|cx, all_traits| {
             for &trait_def_id in all_traits {
                 if !cx.cache.access_levels.is_public(trait_def_id)
-                    || cx.generated_synthetics.get(&(ty, trait_def_id)).is_some()
+                    || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
                 {
                     continue;
                 }
@@ -34,12 +34,12 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         trait_def_id,
                         impl_def_id
                     );
-                    let trait_ref = cx.tcx.impl_trait_ref(impl_def_id).unwrap();
-                    let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_));
+                    let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+                    let is_param = matches!(trait_ref.0.self_ty().kind(), ty::Param(_));
                     let may_apply = is_param && cx.tcx.infer_ctxt().enter(|infcx| {
                         let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
                         let ty = ty.subst(infcx.tcx, substs);
-                        let param_env = param_env.subst(infcx.tcx, substs);
+                        let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
 
                         let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
                         let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
@@ -99,7 +99,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         continue;
                     }
 
-                    cx.generated_synthetics.insert((ty, trait_def_id));
+                    cx.generated_synthetics.insert((ty.0, trait_def_id));
 
                     impls.push(Item {
                         name: None,
@@ -115,15 +115,15 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             ),
                             // FIXME(eddyb) compute both `trait_` and `for_` from
                             // the post-inference `trait_ref`, as it's more accurate.
-                            trait_: Some(trait_ref.clean(cx)),
-                            for_: ty.clean(cx),
+                            trait_: Some(trait_ref.0.clean(cx)),
+                            for_: ty.0.clean(cx),
                             items: cx.tcx
                                 .associated_items(impl_def_id)
                                 .in_definition_order()
                                 .map(|x| x.clean(cx))
                                 .collect::<Vec<_>>(),
                             polarity: ty::ImplPolarity::Positive,
-                            kind: ImplKind::Blanket(box trait_ref.self_ty().clean(cx)),
+                            kind: ImplKind::Blanket(box trait_ref.0.self_ty().clean(cx)),
                         }),
                         cfg: None,
                     });
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7cc96183d6d..6e18f381c59 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -21,7 +21,7 @@ use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_middle::middle::resolve_lifetime as rl;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Lift, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1634,7 +1634,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     .tcx
                     .explicit_item_bounds(def_id)
                     .iter()
-                    .map(|(bound, _)| bound.subst(cx.tcx, substs))
+                    .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
                     .collect::<Vec<_>>();
                 let mut regions = vec![];
                 let mut has_sized = false;
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index d59273db08b..8dd8eb23df2 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -54,7 +54,8 @@ impl DocFS {
     where
         E: PathError,
     {
-        if !self.sync_only && cfg!(windows) {
+        #[cfg(windows)]
+        if !self.sync_only {
             // A possible future enhancement after more detailed profiling would
             // be to create the file sync so errors are reported eagerly.
             let sender = self.errors.clone().expect("can't write after closing");
@@ -68,6 +69,10 @@ impl DocFS {
         } else {
             fs::write(&path, contents).map_err(|e| E::new(e, path))?;
         }
+
+        #[cfg(not(windows))]
+        fs::write(&path, contents).map_err(|e| E::new(e, path))?;
+
         Ok(())
     }
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 56a085c2982..5ba3bdc12ed 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1448,8 +1448,6 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
     // used in tera template files).
     map.insert("mainThemeStyle".into(), 1);
     map.insert("themeStyle".into(), 1);
-    map.insert("theme-picker".into(), 1);
-    map.insert("theme-choices".into(), 1);
     map.insert("settings-menu".into(), 1);
     map.insert("help-button".into(), 1);
     map.insert("main-content".into(), 1);
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 528180288de..81f961992b6 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -596,9 +596,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             |buf: &mut Buffer| {
                 write!(
                     buf,
-                    "<link rel=\"stylesheet\" type=\"text/css\" \
-                        href=\"{root_path}settings{suffix}.css\">\
-                    <script defer src=\"{root_path}settings{suffix}.js\"></script>",
+                    "<div class=\"main-heading\">\
+                     <h1 class=\"fqn\">\
+                         <span class=\"in-band\">Rustdoc settings</span>\
+                     </h1>\
+                     <span class=\"out-of-band\">\
+                         <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+                            Back\
+                        </a>\
+                     </span>\
+                     </div>\
+                     <link rel=\"stylesheet\" type=\"text/css\" \
+                         href=\"{root_path}settings{suffix}.css\">\
+                     <script defer src=\"{root_path}settings{suffix}.js\"></script>",
                     root_path = page.static_root_path.unwrap_or(""),
                     suffix = page.resource_suffix,
                 )
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index e8e5fa17993..ece659284d1 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -238,7 +238,6 @@ pub(super) fn write_shared(
         write_toolchain("favicon-16x16.png", static_files::RUST_FAVICON_PNG_16)?;
         write_toolchain("favicon-32x32.png", static_files::RUST_FAVICON_PNG_32)?;
     }
-    write_toolchain("brush.svg", static_files::BRUSH_SVG)?;
     write_toolchain("wheel.svg", static_files::WHEEL_SVG)?;
     write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?;
     write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?;
@@ -417,7 +416,7 @@ pub(super) fn write_shared(
             ));
             all_sources.sort();
             Ok(format!(
-                "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n",
+                "var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n",
                 all_sources.join("\n")
             )
             .into_bytes())
@@ -439,7 +438,13 @@ pub(super) fn write_shared(
     write_crate("search-index.js", &|| {
         let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
         v.push_str(&all_indexes.join(",\\\n"));
-        v.push_str("\\\n}');\nif (window.initSearch) {window.initSearch(searchIndex)};");
+        v.push_str(
+            r#"\
+}');
+if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
+if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
+"#,
+        );
         Ok(v.into_bytes())
     })?;
 
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index 52577b228aa..7634a15b9bd 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -29,5 +29,10 @@ module.exports = {
         "no-var": ["error"],
         "prefer-const": ["error"],
         "prefer-arrow-callback": ["error"],
+        "brace-style": [
+            "error",
+            "1tbs",
+            { "allowSingleLine": false }
+        ],
     }
 };
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index e35358c5649..0a19a99abf0 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -18,7 +18,3 @@ rules.
 	/* The search bar and related controls don't work without JS */
 	display: none;
 }
-
-#theme-picker {
-	display: none;
-}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 0f4d842f433..4eb8029ee2d 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -897,7 +897,7 @@ table,
 	margin-left: 0.25em;
 	padding-left: 0.3125em;
 	padding-right: 23px;
-	border: 0;
+	border: 1px solid;
 	border-radius: 4px;
 	outline: none;
 	cursor: pointer;
@@ -1379,31 +1379,30 @@ pre.rust {
 	margin-bottom: 6px;
 }
 
-.theme-picker {
-	position: absolute;
-	left: -38px;
-	top: 4px;
-}
-
-.theme-picker button {
-	outline: none;
-}
-
 #settings-menu, #help-button {
 	margin-left: 4px;
 	outline: none;
 }
 
-#theme-picker, #copy-path {
+#copy-path {
 	height: 34px;
 }
-#theme-picker, #settings-menu, #help-button, #copy-path {
+#settings-menu > a, #help-button, #copy-path {
 	padding: 5px;
 	width: 33px;
 	border: 1px solid;
 	border-radius: 2px;
 	cursor: pointer;
 }
+#settings-menu {
+	padding: 0;
+}
+#settings-menu > a {
+	padding: 5px;
+	width: 100%;
+	height: 100%;
+	display: block;
+}
 
 @keyframes rotating {
 	from {
@@ -1413,9 +1412,33 @@ pre.rust {
 		transform: rotate(360deg);
 	}
 }
-#settings-menu.rotate img {
+#settings-menu.rotate > a img {
 	animation: rotating 2s linear infinite;
 }
+#settings-menu #settings {
+	position: absolute;
+	right: 0;
+	z-index: 1;
+	display: block;
+	margin-top: 7px;
+	border-radius: 3px;
+	border: 1px solid;
+}
+#settings-menu #settings .setting-line {
+	margin: 0.6em;
+}
+/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
+#settings-menu #settings::before {
+	content: '';
+	position: absolute;
+	right: 11px;
+	border: solid;
+	border-width: 1px 1px 0 0;
+	display: inline-block;
+	padding: 4px;
+	transform: rotate(-45deg);
+	top: -5px;
+}
 
 #help-button {
 	font-family: "Fira Sans", Arial, sans-serif;
@@ -1838,12 +1861,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		margin-left: 32px;
 	}
 
-	/* Space is at a premium on mobile, so remove the theme-picker icon. */
-	#theme-picker {
-		display: none;
-		width: 0;
-	}
-
 	.content {
 		margin-left: 0px;
 	}
@@ -1993,7 +2010,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 
 	#crate-search {
 		border-radius: 4px;
-		border: 0;
 	}
 
 	.docblock {
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index b1bf06c1865..d32bb4cf22d 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -5,7 +5,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 
 /* General structure and fonts */
 
-body {
+body, #settings-menu #settings, #settings-menu #settings::before {
 	background-color: #0f1419;
 	color: #c5c5c5;
 }
@@ -236,8 +236,8 @@ details.undocumented > summary::before {
 
 #crate-search, .search-input {
 	background-color: #141920;
-	border-color: #424c57;
-	color: #c5c5c5;
+	/* Without the `!important`, the border-color is ignored for `<select>`... */
+	border-color: #424c57 !important;
 }
 
 .search-input {
@@ -531,16 +531,20 @@ kbd {
 	box-shadow: inset 0 -1px 0 #5c6773;
 }
 
-#theme-picker, #settings-menu, #help-button {
+#settings-menu > a, #help-button {
 	border-color: #5c6773;
 	background-color: #0f1419;
 	color: #fff;
 }
 
-#theme-picker > img, #settings-menu > img {
+#settings-menu > a img {
 	filter: invert(100);
 }
 
+#settings-menu #settings, #settings-menu #settings::before {
+	border-color: #5c6773;
+}
+
 #copy-path {
 	color: #fff;
 }
@@ -551,8 +555,7 @@ kbd {
 	filter: invert(100%);
 }
 
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
+#settings-menu > a:hover, #settings-menu > a:focus,
 #help-button:hover, #help-button:focus {
 	border-color: #e0e0e0;
 }
@@ -570,12 +573,6 @@ kbd {
 	background-color: rgba(110, 110, 110, 0.33);
 }
 
-@media (max-width: 700px) {
-	#theme-picker {
-		background: #0f1419;
-	}
-}
-
 .search-results .result-name span.alias {
 	color: #c5c5c5;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 236304ccc9f..4957f25bcf3 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -1,4 +1,4 @@
-body {
+body, #settings-menu #settings, #settings-menu #settings::before {
 	background-color: #353535;
 	color: #ddd;
 }
@@ -217,7 +217,8 @@ details.undocumented > summary::before {
 #crate-search, .search-input {
 	color: #111;
 	background-color: #f0f0f0;
-	border-color: #000;
+	/* Without the `!important`, the border-color is ignored for `<select>`... */
+	border-color: #f0f0f0 !important;
 }
 
 .search-input {
@@ -408,18 +409,21 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#theme-picker, #settings-menu, #help-button {
+#settings-menu > a, #help-button {
 	border-color: #e0e0e0;
 	background: #f0f0f0;
 	color: #000;
 }
 
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
+#settings-menu > a:hover, #settings-menu > a:focus,
 #help-button:hover, #help-button:focus {
 	border-color: #ffb900;
 }
 
+#settings-menu #settings, #settings-menu #settings::before {
+	border-color: #d2d2d2;
+}
+
 #copy-path {
 	color: #999;
 }
@@ -443,12 +447,6 @@ kbd {
 	background-color: #4e4e4e;
 }
 
-@media (max-width: 700px) {
-	#theme-picker {
-		background: #f0f0f0;
-	}
-}
-
 .search-results .result-name span.alias {
 	color: #fff;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index c923902aba2..7d4acc6c611 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -1,6 +1,6 @@
 /* General structure and fonts */
 
-body {
+body, #settings-menu #settings, #settings-menu #settings::before {
 	background-color: white;
 	color: black;
 }
@@ -209,9 +209,9 @@ details.undocumented > summary::before {
 }
 
 #crate-search, .search-input {
-	color: #555;
 	background-color: white;
-	border-color: #e0e0e0;
+	/* Without the `!important`, the border-color is ignored for `<select>`... */
+	border-color: #e0e0e0 !important;
 }
 
 .search-input:focus {
@@ -394,17 +394,20 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#theme-picker, #settings-menu, #help-button {
+#settings-menu > a, #help-button {
 	border-color: #e0e0e0;
 	background-color: #fff;
 }
 
-#theme-picker:hover, #theme-picker:focus,
-#settings-menu:hover, #settings-menu:focus,
+#settings-menu > a:hover, #settings-menu > a:focus,
 #help-button:hover, #help-button:focus {
 	border-color: #717171;
 }
 
+#settings-menu #settings, #settings-menu #settings::before {
+	border-color: #DDDDDD;
+}
+
 #copy-path {
 	color: #999;
 }
@@ -428,12 +431,6 @@ kbd {
 	background-color: #eee;
 }
 
-@media (max-width: 700px) {
-	#theme-picker {
-		background: #fff;
-	}
-}
-
 .search-results .result-name span.alias {
 	color: #000;
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 336223ad28f..454c7f557b9 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1,7 +1,6 @@
 // Local js definitions:
 /* global addClass, getSettingValue, hasClass, searchState */
 /* global onEach, onEachLazy, removeClass */
-/* global switchTheme, useSystemTheme */
 
 "use strict";
 
@@ -109,21 +108,11 @@ function getVirtualKey(ev) {
     return String.fromCharCode(c);
 }
 
-const THEME_PICKER_ELEMENT_ID = "theme-picker";
-const THEMES_ELEMENT_ID = "theme-choices";
 const MAIN_ID = "main-content";
 const SETTINGS_BUTTON_ID = "settings-menu";
 const ALTERNATIVE_DISPLAY_ID = "alternative-display";
 const NOT_DISPLAYED_ID = "not-displayed";
 
-function getThemesElement() {
-    return document.getElementById(THEMES_ELEMENT_ID);
-}
-
-function getThemePickerElement() {
-    return document.getElementById(THEME_PICKER_ELEMENT_ID);
-}
-
 function getSettingsButton() {
     return document.getElementById(SETTINGS_BUTTON_ID);
 }
@@ -133,74 +122,10 @@ function getNakedUrl() {
     return window.location.href.split("?")[0].split("#")[0];
 }
 
-function showThemeButtonState() {
-    const themePicker = getThemePickerElement();
-    const themeChoices = getThemesElement();
-
-    themeChoices.style.display = "block";
-    themePicker.style.borderBottomRightRadius = "0";
-    themePicker.style.borderBottomLeftRadius = "0";
-}
-
-function hideThemeButtonState() {
-    const themePicker = getThemePickerElement();
-    const themeChoices = getThemesElement();
-
-    themeChoices.style.display = "none";
-    themePicker.style.borderBottomRightRadius = "3px";
-    themePicker.style.borderBottomLeftRadius = "3px";
-}
-
 window.hideSettings = () => {
     // Does nothing by default.
 };
 
-// Set up the theme picker list.
-(function () {
-    if (!document.location.href.startsWith("file:///")) {
-        return;
-    }
-    const themeChoices = getThemesElement();
-    const themePicker = getThemePickerElement();
-    const availableThemes = getVar("themes").split(",");
-
-    removeClass(themeChoices.parentElement, "hidden");
-
-    function switchThemeButtonState() {
-        if (themeChoices.style.display === "block") {
-            hideThemeButtonState();
-        } else {
-            showThemeButtonState();
-        }
-    }
-
-    function handleThemeButtonsBlur(e) {
-        const active = document.activeElement;
-        const related = e.relatedTarget;
-
-        if (active.id !== THEME_PICKER_ELEMENT_ID &&
-            (!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
-            (!related ||
-             (related.id !== THEME_PICKER_ELEMENT_ID &&
-              (!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
-            hideThemeButtonState();
-        }
-    }
-
-    themePicker.onclick = switchThemeButtonState;
-    themePicker.onblur = handleThemeButtonsBlur;
-    availableThemes.forEach(item => {
-        const but = document.createElement("button");
-        but.textContent = item;
-        but.onclick = () => {
-            switchTheme(window.currentTheme, window.mainTheme, item, true);
-            useSystemTheme(false);
-        };
-        but.onblur = handleThemeButtonsBlur;
-        themeChoices.appendChild(but);
-    });
-}());
-
 /**
  * This function inserts `newNode` after `referenceNode`. It doesn't work if `referenceNode`
  * doesn't have a parent node.
@@ -512,7 +437,7 @@ function loadCss(cssFileName) {
             ev.preventDefault();
         }
         searchState.defocus();
-        hideThemeButtonState();
+        window.hideSettings();
     }
 
     const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -522,8 +447,6 @@ function loadCss(cssFileName) {
             return;
         }
 
-        let themePicker;
-
         if (document.activeElement.tagName === "INPUT") {
             switch (getVirtualKey(ev)) {
             case "Escape":
@@ -553,64 +476,9 @@ function loadCss(cssFileName) {
                 displayHelp(true, ev);
                 break;
 
-            case "t":
-            case "T":
-                displayHelp(false, ev);
-                ev.preventDefault();
-                themePicker = getThemePickerElement();
-                themePicker.click();
-                themePicker.focus();
-                break;
-
             default:
-                if (getThemePickerElement().parentNode.contains(ev.target)) {
-                    handleThemeKeyDown(ev);
-                }
-            }
-        }
-    }
-
-    function handleThemeKeyDown(ev) {
-        const active = document.activeElement;
-        const themes = getThemesElement();
-        switch (getVirtualKey(ev)) {
-        case "ArrowUp":
-            ev.preventDefault();
-            if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
-                active.previousElementSibling.focus();
-            } else {
-                showThemeButtonState();
-                themes.lastElementChild.focus();
-            }
-            break;
-        case "ArrowDown":
-            ev.preventDefault();
-            if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
-                active.nextElementSibling.focus();
-            } else {
-                showThemeButtonState();
-                themes.firstElementChild.focus();
-            }
-            break;
-        case "Enter":
-        case "Return":
-        case "Space":
-            if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
-                ev.preventDefault();
-                showThemeButtonState();
-                themes.firstElementChild.focus();
+                break;
             }
-            break;
-        case "Home":
-            ev.preventDefault();
-            themes.firstElementChild.focus();
-            break;
-        case "End":
-            ev.preventDefault();
-            themes.lastElementChild.focus();
-            break;
-        // The escape key is handled in handleEscape, not here,
-        // so that pressing escape will close the menu even if it isn't focused
         }
     }
 
@@ -841,8 +709,8 @@ function loadCss(cssFileName) {
             onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
                 if (e.parentNode.id !== "implementations-list" ||
                     (!hasClass(e, "implementors-toggle") &&
-                     !hasClass(e, "type-contents-toggle")))
-                {
+                     !hasClass(e, "type-contents-toggle"))
+                ) {
                     e.open = false;
                 }
             });
@@ -1006,7 +874,6 @@ function loadCss(cssFileName) {
         const shortcuts = [
             ["?", "Show this help dialog"],
             ["S", "Focus the search field"],
-            ["T", "Focus the theme picker menu"],
             ["↑", "Move up in search results"],
             ["↓", "Move down in search results"],
             ["← / →", "Switch result tab (when results focused)"],
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 408b7e19fea..7b9d86a851b 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -98,7 +98,9 @@
             // visible. This is necessary since updateScrapedExample calls scrollToLoc which
             // depends on offsetHeight, a property that requires an element to be visible to
             // compute correctly.
-            setTimeout(() => { onEachLazy(moreExamples, updateScrapedExample); });
+            setTimeout(() => {
+                onEachLazy(moreExamples, updateScrapedExample);
+            });
         }, {once: true});
     });
 })();
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index b596adf32c6..c784d69dcd6 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1,5 +1,5 @@
-/* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
-/* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi */
+/* global addClass, getNakedUrl, getSettingValue */
+/* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */
 
 "use strict";
 
@@ -38,6 +38,11 @@ const itemTypes = [
 // used for special search precedence
 const TY_PRIMITIVE = itemTypes.indexOf("primitive");
 const TY_KEYWORD = itemTypes.indexOf("keyword");
+const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
+
+function hasOwnPropertyRustdoc(obj, property) {
+    return Object.prototype.hasOwnProperty.call(obj, property);
+}
 
 // In the search display, allows to switch between tabs.
 function printTab(nb) {
@@ -106,7 +111,7 @@ function levenshtein(s1, s2) {
     return s1_len + s2_len;
 }
 
-window.initSearch = rawSearchIndex => {
+function initSearch(rawSearchIndex) {
     const MAX_LEV_DISTANCE = 3;
     const MAX_RESULTS = 200;
     const GENERICS_DATA = 2;
@@ -120,15 +125,6 @@ window.initSearch = rawSearchIndex => {
     let searchIndex;
     let currentResults;
     const ALIASES = Object.create(null);
-    const params = searchState.getQueryStringParams();
-
-    // Populate search bar with query string search term when provided,
-    // but only if the input bar is empty. This avoid the obnoxious issue
-    // where you start trying to do a search, and the index loads, and
-    // suddenly your search is gone!
-    if (searchState.input.value === "") {
-        searchState.input.value = params.search || "";
-    }
 
     function isWhitespace(c) {
         return " \t\n\r".indexOf(c) !== -1;
@@ -320,8 +316,8 @@ window.initSearch = rawSearchIndex => {
                     if (foundExclamation) {
                         throw new Error("Cannot have more than one `!` in an ident");
                     } else if (parserState.pos + 1 < parserState.length &&
-                        isIdentCharacter(parserState.userQuery[parserState.pos + 1]))
-                    {
+                        isIdentCharacter(parserState.userQuery[parserState.pos + 1])
+                    ) {
                         throw new Error("`!` can only be at the end of an ident");
                     }
                     foundExclamation = true;
@@ -330,12 +326,10 @@ window.initSearch = rawSearchIndex => {
                 } else if (
                     isStopCharacter(c) ||
                     isSpecialStartCharacter(c) ||
-                    isSeparatorCharacter(c))
-                {
+                    isSeparatorCharacter(c)
+                ) {
                     break;
-                }
-                // If we allow paths ("str::string" for example).
-                else if (c === ":") {
+                } else if (c === ":") { // If we allow paths ("str::string" for example).
                     if (!isPathStart(parserState)) {
                         break;
                     }
@@ -372,8 +366,8 @@ window.initSearch = rawSearchIndex => {
             end = getIdentEndPosition(parserState);
         }
         if (parserState.pos < parserState.length &&
-            parserState.userQuery[parserState.pos] === "<")
-        {
+            parserState.userQuery[parserState.pos] === "<"
+        ) {
             if (isInGenerics) {
                 throw new Error("Unexpected `<` after `<`");
             } else if (start >= end) {
@@ -592,8 +586,8 @@ window.initSearch = rawSearchIndex => {
 
         if (elem &&
             elem.value !== "All crates" &&
-            hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
-        {
+            hasOwnPropertyRustdoc(rawSearchIndex, elem.value)
+        ) {
             return elem.value;
         }
         return null;
@@ -728,10 +722,11 @@ window.initSearch = rawSearchIndex => {
      * @param  {ParsedQuery} parsedQuery - The parsed user query
      * @param  {Object} searchWords      - The list of search words to query against
      * @param  {Object} [filterCrates]   - Crate to search in if defined
+     * @param  {Object} [currentCrate]   - Current crate, to rank results from this crate higher
      *
      * @return {ResultsTable}
      */
-    function execQuery(parsedQuery, searchWords, filterCrates) {
+    function execQuery(parsedQuery, searchWords, filterCrates, currentCrate) {
         const results_others = {}, results_in_args = {}, results_returned = {};
 
         function transformResults(results) {
@@ -763,7 +758,7 @@ window.initSearch = rawSearchIndex => {
             return out;
         }
 
-        function sortResults(results, isType) {
+        function sortResults(results, isType, preferredCrate) {
             const userQuery = parsedQuery.userQuery;
             const ar = [];
             for (const entry in results) {
@@ -786,37 +781,51 @@ window.initSearch = rawSearchIndex => {
                 // sort by exact match with regard to the last word (mismatch goes later)
                 a = (aaa.word !== userQuery);
                 b = (bbb.word !== userQuery);
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // Sort by non levenshtein results and then levenshtein results by the distance
                 // (less changes required to match means higher rankings)
                 a = (aaa.lev);
                 b = (bbb.lev);
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
-                // sort by crate (non-current crate goes later)
-                a = (aaa.item.crate !== window.currentCrate);
-                b = (bbb.item.crate !== window.currentCrate);
-                if (a !== b) { return a - b; }
+                // sort by crate (current crate comes first)
+                a = (aaa.item.crate !== preferredCrate);
+                b = (bbb.item.crate !== preferredCrate);
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // sort by item name length (longer goes later)
                 a = aaa.word.length;
                 b = bbb.word.length;
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // sort by item name (lexicographically larger goes later)
                 a = aaa.word;
                 b = bbb.word;
-                if (a !== b) { return (a > b ? +1 : -1); }
+                if (a !== b) {
+                    return (a > b ? +1 : -1);
+                }
 
                 // sort by index of keyword in item name (no literal occurrence goes later)
                 a = (aaa.index < 0);
                 b = (bbb.index < 0);
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
                 // (later literal occurrence, if any, goes later)
                 a = aaa.index;
                 b = bbb.index;
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // special precedence for primitive and keyword pages
                 if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
@@ -831,17 +840,23 @@ window.initSearch = rawSearchIndex => {
                 // sort by description (no description goes later)
                 a = (aaa.item.desc === "");
                 b = (bbb.item.desc === "");
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // sort by type (later occurrence in `itemTypes` goes later)
                 a = aaa.item.ty;
                 b = bbb.item.ty;
-                if (a !== b) { return a - b; }
+                if (a !== b) {
+                    return a - b;
+                }
 
                 // sort by path (lexicographically larger goes later)
                 a = aaa.item.path;
                 b = bbb.item.path;
-                if (a !== b) { return (a > b ? +1 : -1); }
+                if (a !== b) {
+                    return (a > b ? +1 : -1);
+                }
 
                 // que sera, sera
                 return 0;
@@ -1160,7 +1175,7 @@ window.initSearch = rawSearchIndex => {
             };
         }
 
-        function handleAliases(ret, query, filterCrates) {
+        function handleAliases(ret, query, filterCrates, currentCrate) {
             const lowerQuery = query.toLowerCase();
             // We separate aliases and crate aliases because we want to have current crate
             // aliases to be before the others in the displayed results.
@@ -1176,7 +1191,7 @@ window.initSearch = rawSearchIndex => {
             } else {
                 Object.keys(ALIASES).forEach(crate => {
                     if (ALIASES[crate][lowerQuery]) {
-                        const pushTo = crate === window.currentCrate ? crateAliases : aliases;
+                        const pushTo = crate === currentCrate ? crateAliases : aliases;
                         const query_aliases = ALIASES[crate][lowerQuery];
                         for (const alias of query_aliases) {
                             pushTo.push(createAliasFromItem(searchIndex[alias]));
@@ -1208,8 +1223,9 @@ window.initSearch = rawSearchIndex => {
                     ret.others.pop();
                 }
             };
-            onEach(aliases, pushFunc);
-            onEach(crateAliases, pushFunc);
+
+            aliases.forEach(pushFunc);
+            crateAliases.forEach(pushFunc);
         }
 
         /**
@@ -1315,16 +1331,15 @@ window.initSearch = rawSearchIndex => {
             }
 
             if (searchWord.indexOf(elem.pathLast) > -1 ||
-                row.normalizedName.indexOf(elem.pathLast) > -1)
-            {
+                row.normalizedName.indexOf(elem.pathLast) > -1
+            ) {
                 // filter type: ... queries
                 if (!results_others[fullId] !== undefined) {
                     index = row.normalizedName.indexOf(elem.pathLast);
                 }
             }
             lev = levenshtein(searchWord, elem.pathLast);
-            if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1)
-            {
+            if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) {
                 if (elem.pathLast.length < 6) {
                     lev = 1;
                 } else {
@@ -1427,11 +1442,11 @@ window.initSearch = rawSearchIndex => {
         }
 
         const ret = createQueryResults(
-            sortResults(results_in_args, true),
-            sortResults(results_returned, true),
-            sortResults(results_others, false),
+            sortResults(results_in_args, true, currentCrate),
+            sortResults(results_returned, true, currentCrate),
+            sortResults(results_others, false, currentCrate),
             parsedQuery);
-        handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates);
+        handleAliases(ret, parsedQuery.original.replace(/"/g, ""), filterCrates, currentCrate);
         if (parsedQuery.error !== null && ret.others.length !== 0) {
             // It means some doc aliases were found so let's "remove" the error!
             ret.query.error = null;
@@ -1504,18 +1519,18 @@ window.initSearch = rawSearchIndex => {
 
         if (type === "mod") {
             displayPath = path + "::";
-            href = window.rootPath + path.replace(/::/g, "/") + "/" +
-                   name + "/index.html";
+            href = ROOT_PATH + path.replace(/::/g, "/") + "/" +
+                name + "/index.html";
         } else if (type === "import") {
             displayPath = item.path + "::";
-            href = window.rootPath + item.path.replace(/::/g, "/") + "/index.html#reexport." + name;
+            href = ROOT_PATH + item.path.replace(/::/g, "/") + "/index.html#reexport." + name;
         } else if (type === "primitive" || type === "keyword") {
             displayPath = "";
-            href = window.rootPath + path.replace(/::/g, "/") +
-                   "/" + type + "." + name + ".html";
+            href = ROOT_PATH + path.replace(/::/g, "/") +
+                "/" + type + "." + name + ".html";
         } else if (type === "externcrate") {
             displayPath = "";
-            href = window.rootPath + name + "/index.html";
+            href = ROOT_PATH + name + "/index.html";
         } else if (item.parent !== undefined) {
             const myparent = item.parent;
             let anchor = "#" + type + "." + name;
@@ -1538,14 +1553,14 @@ window.initSearch = rawSearchIndex => {
             } else {
                 displayPath = path + "::" + myparent.name + "::";
             }
-            href = window.rootPath + path.replace(/::/g, "/") +
-                   "/" + pageType +
-                   "." + pageName +
-                   ".html" + anchor;
+            href = ROOT_PATH + path.replace(/::/g, "/") +
+                "/" + pageType +
+                "." + pageName +
+                ".html" + anchor;
         } else {
             displayPath = item.path + "::";
-            href = window.rootPath + item.path.replace(/::/g, "/") +
-                   "/" + type + "." + name + ".html";
+            href = ROOT_PATH + item.path.replace(/::/g, "/") +
+                "/" + type + "." + name + ".html";
         }
         return [displayPath, href];
     }
@@ -1670,8 +1685,8 @@ window.initSearch = rawSearchIndex => {
             // By default, the search DOM element is "empty" (meaning it has no children not
             // text content). Once a search has been run, it won't be empty, even if you press
             // ESC or empty the search input (which also "cancels" the search).
-            && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText)))
-        {
+            && (!search.firstChild || search.firstChild.innerText !== searchState.loadingText))
+        ) {
             const elem = document.createElement("a");
             elem.href = results.others[0].href;
             removeClass(elem, "active");
@@ -1723,7 +1738,7 @@ window.initSearch = rawSearchIndex => {
 
         let output = "<div id=\"search-settings\">" +
             `<h1 class="search-results-title">Results for ${escape(results.query.userQuery)}` +
-            `${typeFilter}</h1> in ${crates} </div>`;
+            `${typeFilter}</h1>${crates}</div>`;
         if (results.query.error !== null) {
             output += `<h3>Query parser error: "${results.query.error}".</h3>`;
             output += "<div id=\"titles\">" +
@@ -1766,7 +1781,7 @@ window.initSearch = rawSearchIndex => {
         let i = 0;
         for (const elem of elems) {
             const j = i;
-            elem.onclick = () => { printTab(j); };
+            elem.onclick = () => printTab(j);
             searchState.focusedByTab.push(null);
             i += 1;
         }
@@ -1818,7 +1833,7 @@ window.initSearch = rawSearchIndex => {
         }
 
         showResults(
-            execQuery(query, searchWords, filterCrates),
+            execQuery(query, searchWords, filterCrates, window.currentCrate),
             params.go_to_first,
             filterCrates);
     }
@@ -1998,6 +2013,16 @@ window.initSearch = rawSearchIndex => {
     }
 
     function registerSearchEvents() {
+        const params = searchState.getQueryStringParams();
+
+        // Populate search bar with query string search term when provided,
+        // but only if the input bar is empty. This avoid the obnoxious issue
+        // where you start trying to do a search, and the index loads, and
+        // suddenly your search is gone!
+        if (searchState.input.value === "") {
+            searchState.input.value = params.search || "";
+        }
+
         const searchAfter500ms = () => {
             searchState.clearInputTimeout();
             if (searchState.input.value.length === 0) {
@@ -2150,20 +2175,32 @@ window.initSearch = rawSearchIndex => {
      *  @type {Array<string>}
      */
     const searchWords = buildIndex(rawSearchIndex);
-    registerSearchEvents();
-
-    function runSearchIfNeeded() {
+    if (typeof window !== "undefined") {
+        registerSearchEvents();
         // If there's a search term in the URL, execute the search now.
-        if (searchState.getQueryStringParams().search) {
+        if (window.searchState.getQueryStringParams().search) {
             search();
         }
     }
 
-    runSearchIfNeeded();
-};
+    if (typeof exports !== "undefined") {
+        exports.initSearch = initSearch;
+        exports.execQuery = execQuery;
+        exports.parseQuery = parseQuery;
+    }
+    return searchWords;
+}
 
-if (window.searchIndex !== undefined) {
-    initSearch(window.searchIndex);
+if (typeof window !== "undefined") {
+    window.initSearch = initSearch;
+    if (window.searchIndex !== undefined) {
+        initSearch(window.searchIndex);
+    }
+} else {
+    // Running in Node, not a browser. Run initSearch just to produce the
+    // exports.
+    initSearch({});
 }
 
+
 })();
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index ad32a193893..8770cc3f3b1 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,7 +1,7 @@
 // Local js definitions:
 /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
-/* global addClass, removeClass, onEach, onEachLazy, NOT_DISPLAYED_ID */
-/* global MAIN_ID, getVar, getSettingsButton, switchDisplayedElement, getNotDisplayedElem */
+/* global addClass, removeClass, onEach, onEachLazy */
+/* global MAIN_ID, getVar, getSettingsButton */
 
 "use strict";
 
@@ -206,38 +206,46 @@
         ];
 
         // Then we build the DOM.
-        const el = document.createElement("section");
+        const elementKind = isSettingsPage ? "section" : "div";
+        const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
+        const el = document.createElement(elementKind);
         el.id = "settings";
-        let innerHTML = `
-            <div class="main-heading">
-                <h1 class="fqn">
-                    <span class="in-band">Rustdoc settings</span>
-                </h1>
-                <span class="out-of-band">`;
-
-        if (isSettingsPage) {
-            innerHTML +=
-                "<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">Back</a>";
-        } else {
-            innerHTML += "<a id=\"back\" href=\"javascript:void(0)\" " +
-                "onclick=\"switchDisplayedElement(null);\">Back</a>";
-        }
-        innerHTML += `</span>
-            </div>
-            <div class="settings">${buildSettingsPageSections(settings)}</div>`;
-
         el.innerHTML = innerHTML;
 
         if (isSettingsPage) {
             document.getElementById(MAIN_ID).appendChild(el);
         } else {
-            getNotDisplayedElem().appendChild(el);
+            el.setAttribute("tabindex", "-1");
+            getSettingsButton().appendChild(el);
         }
         return el;
     }
 
     const settingsMenu = buildSettingsPage();
 
+    function displaySettings() {
+        settingsMenu.style.display = "";
+    }
+
+    function elemIsInParent(elem, parent) {
+        while (elem && elem !== document.body) {
+            if (elem === parent) {
+                return true;
+            }
+            elem = elem.parentElement;
+        }
+        return false;
+    }
+
+    function blurHandler(event) {
+        const settingsButton = getSettingsButton();
+        if (!elemIsInParent(document.activeElement, settingsButton) &&
+            !elemIsInParent(event.relatedTarget, settingsButton)
+        ) {
+            window.hideSettings();
+        }
+    }
+
     if (isSettingsPage) {
         // We replace the existing "onclick" callback to do nothing if clicked.
         getSettingsButton().onclick = function(event) {
@@ -246,17 +254,27 @@
     } else {
         // We replace the existing "onclick" callback.
         const settingsButton = getSettingsButton();
+        const settingsMenu = document.getElementById("settings");
+        window.hideSettings = function() {
+            settingsMenu.style.display = "none";
+        };
         settingsButton.onclick = function(event) {
+            if (elemIsInParent(event.target, settingsMenu)) {
+                return;
+            }
             event.preventDefault();
-            if (settingsMenu.parentElement.id === NOT_DISPLAYED_ID) {
-                switchDisplayedElement(settingsMenu);
-            } else {
+            if (settingsMenu.style.display !== "none") {
                 window.hideSettings();
+            } else {
+                displaySettings();
             }
         };
-        window.hideSettings = function() {
-            switchDisplayedElement(null);
-        };
+        settingsButton.onblur = blurHandler;
+        settingsButton.querySelector("a").onblur = blurHandler;
+        onEachLazy(settingsMenu.querySelectorAll("input"), el => {
+            el.onblur = blurHandler;
+        });
+        settingsMenu.onblur = blurHandler;
     }
 
     // We now wait a bit for the web browser to end re-computing the DOM...
@@ -264,7 +282,7 @@
         setEvents(settingsMenu);
         // The setting menu is already displayed if we're on the settings page.
         if (!isSettingsPage) {
-            switchDisplayedElement(settingsMenu);
+            displaySettings();
         }
         removeClass(getSettingsButton(), "rotate");
     }, 0);
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 21de7d77d64..948885cd30a 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -100,11 +100,6 @@ function onEachLazy(lazyArray, func, reversed) {
         reversed);
 }
 
-// eslint-disable-next-line no-unused-vars
-function hasOwnPropertyRustdoc(obj, property) {
-    return Object.prototype.hasOwnProperty.call(obj, property);
-}
-
 function updateLocalStorage(name, value) {
     try {
         window.localStorage.setItem("rustdoc-" + name, value);
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index bec5c083fed..85ca8431d90 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -41,9 +41,6 @@ crate static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.
 
 crate static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");
 
-/// The file contents of `brush.svg`, the icon used for the theme-switch button.
-crate static BRUSH_SVG: &[u8] = include_bytes!("static/images/brush.svg");
-
 /// The file contents of `wheel.svg`, the icon used for the settings button.
 crate static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg");
 
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 470cce93a50..cd672aadd7e 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -108,13 +108,6 @@
                     {%- endif -%}
                 </a> {#- -#}
                 <nav class="sub"> {#- -#}
-                    <div class="theme-picker hidden"> {#- -#}
-                        <button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"> {#- -#}
-                            <img width="22" height="22" alt="Pick another theme!" {# -#}
-                             src="{{static_root_path|safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
-                        </button> {#- -#}
-                        <div id="theme-choices" role="menu"></div> {#- -#}
-                    </div> {#- -#}
                     <form class="search-form"> {#- -#}
                         <div class="search-container"> {#- -#}
                             <span></span> {#- This empty span is a hacky fix for Safari - See #93184 -#}
@@ -126,10 +119,12 @@
                                 placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
                                 type="search"> {#- -#}
                             <button type="button" id="help-button" title="help">?</button> {#- -#}
-                            <a id="settings-menu" href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
-                                <img width="22" height="22" alt="Change settings" {# -#}
+                            <div id="settings-menu" tabindex="-1">
+                                <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
+                                    <img width="22" height="22" alt="Change settings" {# -#}
                                      src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
-                            </a> {#- -#}
+                                </a> {#- -#}
+                            </div>
                         </div> {#- -#}
                     </form> {#- -#}
                 </nav> {#- -#}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 56b02cd8480..412387313dc 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -350,10 +350,16 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
     fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
         use clean::WherePredicate::*;
         match predicate {
-            BoundPredicate { ty, bounds, .. } => WherePredicate::BoundPredicate {
+            BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
                 type_: ty.into_tcx(tcx),
                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
-                // FIXME: add `bound_params` to rustdoc-json-params?
+                generic_params: bound_params
+                    .into_iter()
+                    .map(|x| GenericParamDef {
+                        name: x.0.to_string(),
+                        kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+                    })
+                    .collect(),
             },
             RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
                 lifetime: lifetime.0.to_string(),
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 22b2f8c0c8e..95ba4ce5b06 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -11,12 +11,12 @@ use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::Mutability;
 use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug, ty};
+use rustc_middle::{bug, ty};
 use rustc_resolve::ParentScope;
 use rustc_session::lint::Lint;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{BytePos, DUMMY_SP};
+use rustc_span::BytePos;
 use smallvec::{smallvec, SmallVec};
 
 use std::borrow::Cow;
@@ -48,18 +48,6 @@ fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
     krate
 }
 
-/// Top-level errors emitted by this pass.
-enum ErrorKind<'a> {
-    Resolve(Box<ResolutionFailure<'a>>),
-    AnchorFailure(AnchorFailure),
-}
-
-impl<'a> From<ResolutionFailure<'a>> for ErrorKind<'a> {
-    fn from(err: ResolutionFailure<'a>) -> Self {
-        ErrorKind::Resolve(box err)
-    }
-}
-
 #[derive(Copy, Clone, Debug, Hash)]
 enum Res {
     Def(DefKind, DefId),
@@ -97,12 +85,8 @@ impl Res {
         }
     }
 
-    fn as_hir_res(self) -> Option<rustc_hir::def::Res> {
-        match self {
-            Res::Def(kind, id) => Some(rustc_hir::def::Res::Def(kind, id)),
-            // FIXME: maybe this should handle the subset of PrimitiveType that fits into hir::PrimTy?
-            Res::Primitive(_) => None,
-        }
+    fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Res {
+        Res::Def(tcx.def_kind(def_id), def_id)
     }
 
     /// Used for error reporting.
@@ -160,8 +144,25 @@ impl TryFrom<ResolveRes> for Res {
     }
 }
 
-/// A link failed to resolve.
-#[derive(Clone, Debug)]
+/// The link failed to resolve. [`resolution_failure`] should look to see if there's
+/// a more helpful error that can be given.
+#[derive(Debug)]
+struct UnresolvedPath<'a> {
+    /// Item on which the link is resolved, used for resolving `Self`.
+    item_id: ItemId,
+    /// The scope the link was resolved in.
+    module_id: DefId,
+    /// If part of the link resolved, this has the `Res`.
+    ///
+    /// In `[std::io::Error::x]`, `std::io::Error` would be a partial resolution.
+    partial_res: Option<Res>,
+    /// The remaining unresolved path segments.
+    ///
+    /// In `[std::io::Error::x]`, `x` would be unresolved.
+    unresolved: Cow<'a, str>,
+}
+
+#[derive(Debug)]
 enum ResolutionFailure<'a> {
     /// This resolved, but with the wrong namespace.
     WrongNamespace {
@@ -173,35 +174,10 @@ enum ResolutionFailure<'a> {
         /// even though `Result`'s actual namespace is [`Namespace::TypeNS`].
         expected_ns: Namespace,
     },
-    /// The link failed to resolve. [`resolution_failure`] should look to see if there's
-    /// a more helpful error that can be given.
-    NotResolved {
-        /// Item on which the link is resolved, used for resolving `Self`.
-        item_id: ItemId,
-        /// The scope the link was resolved in.
-        module_id: DefId,
-        /// If part of the link resolved, this has the `Res`.
-        ///
-        /// In `[std::io::Error::x]`, `std::io::Error` would be a partial resolution.
-        partial_res: Option<Res>,
-        /// The remaining unresolved path segments.
-        ///
-        /// In `[std::io::Error::x]`, `x` would be unresolved.
-        unresolved: Cow<'a, str>,
-    },
-    /// This happens when rustdoc can't determine the parent scope for an item.
-    /// It is always a bug in rustdoc.
-    NoParentItem,
-    /// This link has malformed generic parameters; e.g., the angle brackets are unbalanced.
-    MalformedGenerics(MalformedGenerics),
-    /// Used to communicate that this should be ignored, but shouldn't be reported to the user.
-    ///
-    /// This happens when there is no disambiguator and one of the namespaces
-    /// failed to resolve.
-    Dummy,
+    NotResolved(UnresolvedPath<'a>),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug)]
 enum MalformedGenerics {
     /// This link has unbalanced angle brackets.
     ///
@@ -242,35 +218,6 @@ enum MalformedGenerics {
     EmptyAngleBrackets,
 }
 
-impl ResolutionFailure<'_> {
-    /// This resolved fully (not just partially) but is erroneous for some other reason
-    ///
-    /// Returns the full resolution of the link, if present.
-    fn full_res(&self) -> Option<Res> {
-        match self {
-            Self::WrongNamespace { res, expected_ns: _ } => Some(*res),
-            _ => None,
-        }
-    }
-}
-
-#[derive(Clone, Copy)]
-enum AnchorFailure {
-    /// User error: `[std#x#y]` is not valid
-    MultipleAnchors,
-    /// The anchor provided by the user conflicts with Rustdoc's generated anchor.
-    ///
-    /// This is an unfortunate state of affairs. Not every item that can be
-    /// linked to has its own page; sometimes it is a subheading within a page,
-    /// like for associated items. In those cases, rustdoc uses an anchor to
-    /// link to the subheading. Since you can't have two anchors for the same
-    /// link, Rustdoc disallows having a user-specified anchor.
-    ///
-    /// Most of the time this is fine, because you can just link to the page of
-    /// the item if you want to provide your own anchor.
-    RustdocAnchorConflict(Res),
-}
-
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 crate enum UrlFragment {
     Item(ItemFragment),
@@ -302,24 +249,32 @@ crate enum FragmentKind {
     VariantField,
 }
 
-impl ItemFragment {
-    /// Create a fragment for an associated item.
-    #[instrument(level = "debug")]
-    fn from_assoc_item(item: &ty::AssocItem) -> Self {
-        let def_id = item.def_id;
-        match item.kind {
-            ty::AssocKind::Fn => {
-                if item.defaultness.has_value() {
-                    ItemFragment(FragmentKind::Method, def_id)
+impl FragmentKind {
+    fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> FragmentKind {
+        match tcx.def_kind(def_id) {
+            DefKind::AssocFn => {
+                if tcx.associated_item(def_id).defaultness.has_value() {
+                    FragmentKind::Method
+                } else {
+                    FragmentKind::TyMethod
+                }
+            }
+            DefKind::AssocConst => FragmentKind::AssociatedConstant,
+            DefKind::AssocTy => FragmentKind::AssociatedType,
+            DefKind::Variant => FragmentKind::Variant,
+            DefKind::Field => {
+                if tcx.def_kind(tcx.parent(def_id)) == DefKind::Variant {
+                    FragmentKind::VariantField
                 } else {
-                    ItemFragment(FragmentKind::TyMethod, def_id)
+                    FragmentKind::StructField
                 }
             }
-            ty::AssocKind::Const => ItemFragment(FragmentKind::AssociatedConstant, def_id),
-            ty::AssocKind::Type => ItemFragment(FragmentKind::AssociatedType, def_id),
+            kind => bug!("unexpected associated item kind: {:?}", kind),
         }
     }
+}
 
+impl ItemFragment {
     /// Render the fragment, including the leading `#`.
     crate fn render(&self, s: &mut String, tcx: TyCtxt<'_>) -> std::fmt::Result {
         write!(s, "#")?;
@@ -389,9 +344,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         path_str: &'path str,
         item_id: ItemId,
         module_id: DefId,
-    ) -> Result<(Res, Option<ItemFragment>), ErrorKind<'path>> {
+    ) -> Result<(Res, DefId), UnresolvedPath<'path>> {
         let tcx = self.cx.tcx;
-        let no_res = || ResolutionFailure::NotResolved {
+        let no_res = || UnresolvedPath {
             item_id,
             module_id,
             partial_res: None,
@@ -418,42 +373,27 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?;
 
         match ty_res {
-            Res::Def(DefKind::Enum, did) => {
-                if tcx
-                    .inherent_impls(did)
-                    .iter()
-                    .flat_map(|imp| tcx.associated_items(*imp).in_definition_order())
-                    .any(|item| item.name == variant_name)
-                {
-                    // This is just to let `fold_item` know that this shouldn't be considered;
-                    // it's a bug for the error to make it to the user
-                    return Err(ResolutionFailure::Dummy.into());
-                }
-                match tcx.type_of(did).kind() {
-                    ty::Adt(def, _) if def.is_enum() => {
-                        if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name)
-                        {
-                            Ok((ty_res, Some(ItemFragment(FragmentKind::VariantField, field.did))))
-                        } else {
-                            Err(ResolutionFailure::NotResolved {
-                                item_id,
-                                module_id,
-                                partial_res: Some(Res::Def(DefKind::Enum, def.did())),
-                                unresolved: variant_field_name.to_string().into(),
-                            }
-                            .into())
-                        }
+            Res::Def(DefKind::Enum, did) => match tcx.type_of(did).kind() {
+                ty::Adt(def, _) if def.is_enum() => {
+                    if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name) {
+                        Ok((ty_res, field.did))
+                    } else {
+                        Err(UnresolvedPath {
+                            item_id,
+                            module_id,
+                            partial_res: Some(Res::Def(DefKind::Enum, def.did())),
+                            unresolved: variant_field_name.to_string().into(),
+                        })
                     }
-                    _ => unreachable!(),
                 }
-            }
-            _ => Err(ResolutionFailure::NotResolved {
+                _ => unreachable!(),
+            },
+            _ => Err(UnresolvedPath {
                 item_id,
                 module_id,
                 partial_res: Some(ty_res),
                 unresolved: variant_name.to_string().into(),
-            }
-            .into()),
+            }),
         }
     }
 
@@ -463,35 +403,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         prim_ty: PrimitiveType,
         ns: Namespace,
         item_name: Symbol,
-    ) -> Option<(Res, ItemFragment)> {
+    ) -> Option<(Res, DefId)> {
         let tcx = self.cx.tcx;
 
         prim_ty.impls(tcx).find_map(|impl_| {
             tcx.associated_items(impl_)
                 .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
-                .map(|item| {
-                    let fragment = ItemFragment::from_assoc_item(item);
-                    (Res::Primitive(prim_ty), fragment)
-                })
-        })
-    }
-
-    /// Resolves a string as a macro.
-    ///
-    /// FIXME(jynelson): Can this be unified with `resolve()`?
-    fn resolve_macro(
-        &self,
-        path_str: &'a str,
-        item_id: ItemId,
-        module_id: DefId,
-    ) -> Result<Res, ResolutionFailure<'a>> {
-        self.resolve_path(path_str, MacroNS, item_id, module_id).ok_or_else(|| {
-            ResolutionFailure::NotResolved {
-                item_id,
-                module_id,
-                partial_res: None,
-                unresolved: path_str.into(),
-            }
+                .map(|item| (Res::Primitive(prim_ty), item.def_id))
         })
     }
 
@@ -525,21 +443,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             })
     }
 
-    /// HACK: Try to search the macro name in the list of all `macro_rules` items in the crate.
-    /// Used when nothing else works, may often give an incorrect result.
-    fn resolve_macro_rules(&self, path_str: &str, ns: Namespace) -> Option<Res> {
-        if ns != MacroNS {
-            return None;
-        }
-
-        self.cx
-            .resolver_caches
-            .all_macro_rules
-            .get(&Symbol::intern(path_str))
-            .copied()
-            .and_then(|res| res.try_into().ok())
-    }
-
     /// Convenience wrapper around `resolve_rustdoc_path`.
     ///
     /// This also handles resolving `true` and `false` as booleans.
@@ -571,8 +474,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 })
             })
             .and_then(|res| res.try_into().ok())
-            .or_else(|| resolve_primitive(path_str, ns))
-            .or_else(|| self.resolve_macro_rules(path_str, ns));
+            .or_else(|| resolve_primitive(path_str, ns));
         debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
         result
     }
@@ -585,43 +487,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         ns: Namespace,
         item_id: ItemId,
         module_id: DefId,
-        user_fragment: &Option<String>,
-    ) -> Result<(Res, Option<UrlFragment>), ErrorKind<'path>> {
-        let (res, rustdoc_fragment) = self.resolve_inner(path_str, ns, item_id, module_id)?;
-        let chosen_fragment = match (user_fragment, rustdoc_fragment) {
-            (Some(_), Some(r_frag)) => {
-                let diag_res = match r_frag {
-                    ItemFragment(_, did) => Res::Def(self.cx.tcx.def_kind(did), did),
-                };
-                let failure = AnchorFailure::RustdocAnchorConflict(diag_res);
-                return Err(ErrorKind::AnchorFailure(failure));
-            }
-            (Some(u_frag), None) => Some(UrlFragment::UserWritten(u_frag.clone())),
-            (None, Some(r_frag)) => Some(UrlFragment::Item(r_frag)),
-            (None, None) => None,
-        };
-        Ok((res, chosen_fragment))
-    }
-
-    fn resolve_inner<'path>(
-        &mut self,
-        path_str: &'path str,
-        ns: Namespace,
-        item_id: ItemId,
-        module_id: DefId,
-    ) -> Result<(Res, Option<ItemFragment>), ErrorKind<'path>> {
+    ) -> Result<(Res, Option<DefId>), UnresolvedPath<'path>> {
         if let Some(res) = self.resolve_path(path_str, ns, item_id, module_id) {
-            match res {
-                // FIXME(#76467): make this fallthrough to lookup the associated
-                // item a separate function.
-                Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
-                Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
-                Res::Def(DefKind::Variant, _) => {
-                    return handle_variant(self.cx, res);
-                }
-                // Not a trait item; just return what we found.
-                _ => return Ok((res, None)),
-            }
+            return Ok(match res {
+                Res::Def(
+                    DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Variant,
+                    def_id,
+                ) => (Res::from_def_id(self.cx.tcx, self.cx.tcx.parent(def_id)), Some(def_id)),
+                _ => ((res, None)),
+            });
+        } else if ns == MacroNS {
+            return Err(UnresolvedPath {
+                item_id,
+                module_id,
+                partial_res: None,
+                unresolved: path_str.into(),
+            });
         }
 
         // Try looking for methods and associated items.
@@ -637,7 +518,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             // So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
             .ok_or_else(|| {
                 debug!("found no `::`, assumming {} was correctly not in scope", item_name);
-                ResolutionFailure::NotResolved {
+                UnresolvedPath {
                     item_id,
                     module_id,
                     partial_res: None,
@@ -652,24 +533,21 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         resolve_primitive(&path_root, TypeNS)
             .or_else(|| self.resolve_path(&path_root, TypeNS, item_id, module_id))
             .and_then(|ty_res| {
-                let (res, fragment) =
-                    self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
-
-                Some(Ok((res, Some(fragment))))
+                self.resolve_associated_item(ty_res, item_name, ns, module_id).map(Ok)
             })
             .unwrap_or_else(|| {
                 if ns == Namespace::ValueNS {
                     self.variant_field(path_str, item_id, module_id)
                 } else {
-                    Err(ResolutionFailure::NotResolved {
+                    Err(UnresolvedPath {
                         item_id,
                         module_id,
                         partial_res: None,
                         unresolved: path_root.into(),
-                    }
-                    .into())
+                    })
                 }
             })
+            .map(|(res, def_id)| (res, Some(def_id)))
     }
 
     /// Convert a DefId to a Res, where possible.
@@ -694,7 +572,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             ty::FnPtr(_) => Res::Primitive(Fn),
             ty::Never => Res::Primitive(Never),
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
-                Res::Def(self.cx.tcx.def_kind(did), did)
+                Res::from_def_id(self.cx.tcx, did)
             }
             ty::Projection(_)
             | ty::Closure(..)
@@ -751,23 +629,18 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         item_name: Symbol,
         ns: Namespace,
         module_id: DefId,
-    ) -> Option<(Res, ItemFragment)> {
+    ) -> Option<(Res, DefId)> {
         let tcx = self.cx.tcx;
 
         match root_res {
             Res::Primitive(prim) => {
                 self.resolve_primitive_associated_item(prim, ns, item_name).or_else(|| {
-                    let assoc_item = self
-                        .primitive_type_to_ty(prim)
+                    self.primitive_type_to_ty(prim)
                         .map(|ty| {
                             resolve_associated_trait_item(ty, module_id, item_name, ns, self.cx)
                         })
-                        .flatten();
-
-                    assoc_item.map(|item| {
-                        let fragment = ItemFragment::from_assoc_item(&item);
-                        (root_res, fragment)
-                    })
+                        .flatten()
+                        .map(|item| (root_res, item.def_id))
                 })
             }
             Res::Def(DefKind::TyAlias, did) => {
@@ -788,10 +661,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ty::Adt(adt_def, _) => {
                             for variant in adt_def.variants() {
                                 if variant.name == item_name {
-                                    return Some((
-                                        root_res,
-                                        ItemFragment(FragmentKind::Variant, variant.def_id),
-                                    ));
+                                    return Some((root_res, variant.def_id));
                                 }
                             }
                         }
@@ -832,8 +702,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 debug!("got associated item {:?}", assoc_item);
 
                 if let Some(item) = assoc_item {
-                    let fragment = ItemFragment::from_assoc_item(&item);
-                    return Some((root_res, fragment));
+                    return Some((root_res, item.def_id));
                 }
 
                 if ns != Namespace::ValueNS {
@@ -861,59 +730,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 };
                 let field =
                     def.non_enum_variant().fields.iter().find(|item| item.name == item_name)?;
-                Some((root_res, ItemFragment(FragmentKind::StructField, field.did)))
+                Some((root_res, field.did))
             }
             Res::Def(DefKind::Trait, did) => tcx
                 .associated_items(did)
                 .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
                 .map(|item| {
-                    let fragment = ItemFragment::from_assoc_item(item);
                     let res = Res::Def(item.kind.as_def_kind(), item.def_id);
-                    (res, fragment)
+                    (res, item.def_id)
                 }),
             _ => None,
         }
     }
+}
 
-    /// Used for reporting better errors.
-    ///
-    /// Returns whether the link resolved 'fully' in another namespace.
-    /// 'fully' here means that all parts of the link resolved, not just some path segments.
-    /// This returns the `Res` even if it was erroneous for some reason
-    /// (such as having invalid URL fragments or being in the wrong namespace).
-    fn check_full_res(
-        &mut self,
-        ns: Namespace,
-        path_str: &str,
-        item_id: ItemId,
-        module_id: DefId,
-        extra_fragment: &Option<String>,
-    ) -> Option<Res> {
-        // resolve() can't be used for macro namespace
-        let result = match ns {
-            Namespace::MacroNS => self
-                .resolve_macro(path_str, item_id, module_id)
-                .map(|res| (res, None))
-                .map_err(ErrorKind::from),
-            Namespace::TypeNS | Namespace::ValueNS => {
-                self.resolve(path_str, ns, item_id, module_id, extra_fragment)
-            }
-        };
-
-        let res = match result {
-            Ok((res, frag)) => {
-                if let Some(UrlFragment::Item(ItemFragment(_, id))) = frag {
-                    Some(Res::Def(self.cx.tcx.def_kind(id), id))
-                } else {
-                    Some(res)
-                }
-            }
-            Err(ErrorKind::Resolve(box kind)) => kind.full_res(),
-            Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res))) => Some(res),
-            Err(ErrorKind::AnchorFailure(AnchorFailure::MultipleAnchors)) => None,
-        };
-        res
-    }
+fn full_res(tcx: TyCtxt<'_>, (base, assoc_item): (Res, Option<DefId>)) -> Res {
+    assoc_item.map_or(base, |def_id| Res::from_def_id(tcx, def_id))
 }
 
 /// Look to see if a resolved item has an associated item named `item_name`.
@@ -1093,14 +925,23 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
 }
 
 enum PreprocessingError {
-    Anchor(AnchorFailure),
+    /// User error: `[std#x#y]` is not valid
+    MultipleAnchors,
     Disambiguator(Range<usize>, String),
-    Resolution(ResolutionFailure<'static>, String, Option<Disambiguator>),
+    MalformedGenerics(MalformedGenerics, String),
 }
 
-impl From<AnchorFailure> for PreprocessingError {
-    fn from(err: AnchorFailure) -> Self {
-        Self::Anchor(err)
+impl PreprocessingError {
+    fn report(&self, cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
+        match self {
+            PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
+            PreprocessingError::Disambiguator(range, msg) => {
+                disambiguator_error(cx, diag_info, range.clone(), msg)
+            }
+            PreprocessingError::MalformedGenerics(err, path_str) => {
+                report_malformed_generics(cx, diag_info, *err, path_str)
+            }
+        }
     }
 }
 
@@ -1145,7 +986,7 @@ fn preprocess_link(
     let extra_fragment = parts.next();
     if parts.next().is_some() {
         // A valid link can't have multiple #'s
-        return Some(Err(AnchorFailure::MultipleAnchors.into()));
+        return Some(Err(PreprocessingError::MultipleAnchors));
     }
 
     // Parse and strip the disambiguator from the link, if present.
@@ -1173,13 +1014,9 @@ fn preprocess_link(
     let path_str = if path_str.contains(['<', '>'].as_slice()) {
         match strip_generics_from_path(path_str) {
             Ok(path) => path,
-            Err(err_kind) => {
+            Err(err) => {
                 debug!("link has malformed generics: {}", path_str);
-                return Some(Err(PreprocessingError::Resolution(
-                    err_kind,
-                    path_str.to_owned(),
-                    disambiguator,
-                )));
+                return Some(Err(PreprocessingError::MalformedGenerics(err, path_str.to_owned())));
             }
         }
     } else {
@@ -1229,32 +1066,10 @@ impl LinkCollector<'_, '_> {
             link_range: ori_link.range.clone(),
         };
 
-        let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } = match pp_link
-        {
-            Ok(x) => x,
-            Err(err) => {
-                match err {
-                    PreprocessingError::Anchor(err) => anchor_failure(self.cx, diag_info, *err),
-                    PreprocessingError::Disambiguator(range, msg) => {
-                        disambiguator_error(self.cx, diag_info, range.clone(), msg)
-                    }
-                    PreprocessingError::Resolution(err, path_str, disambiguator) => {
-                        resolution_failure(
-                            self,
-                            diag_info,
-                            path_str,
-                            *disambiguator,
-                            smallvec![err.clone()],
-                        );
-                    }
-                }
-                return None;
-            }
-        };
+        let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
+            pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
         let disambiguator = *disambiguator;
 
-        let inner_docs = item.inner_docs(self.cx.tcx);
-
         // In order to correctly resolve intra-doc links we need to
         // pick a base AST node to work from.  If the documentation for
         // this module came from an inner comment (//!) then we anchor
@@ -1266,21 +1081,10 @@ impl LinkCollector<'_, '_> {
         // we've already pushed this node onto the resolution stack but
         // for outer comments we explicitly try and resolve against the
         // parent_node first.
+        let inner_docs = item.inner_docs(self.cx.tcx);
         let base_node =
             if item.is_mod() && inner_docs { self.mod_ids.last().copied() } else { parent_node };
-
-        let Some(module_id) = base_node else {
-            // This is a bug.
-            debug!("attempting to resolve item without parent module: {}", path_str);
-            resolution_failure(
-                self,
-                diag_info,
-                path_str,
-                disambiguator,
-                smallvec![ResolutionFailure::NoParentItem],
-            );
-            return None;
-        };
+        let module_id = base_node.expect("doc link without parent module");
 
         let (mut res, fragment) = self.resolve_with_disambiguator_cached(
             ResolutionInfo {
@@ -1504,7 +1308,21 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let res = self.resolve_with_disambiguator(&key, diag);
+        let res = self.resolve_with_disambiguator(&key, diag.clone()).and_then(|(res, def_id)| {
+            let fragment = match (&key.extra_fragment, def_id) {
+                (Some(_), Some(def_id)) => {
+                    report_anchor_conflict(self.cx, diag, Res::from_def_id(self.cx.tcx, def_id));
+                    return None;
+                }
+                (Some(u_frag), None) => Some(UrlFragment::UserWritten(u_frag.clone())),
+                (None, Some(def_id)) => Some(UrlFragment::Item(ItemFragment(
+                    FragmentKind::from_def_id(self.cx.tcx, def_id),
+                    def_id,
+                ))),
+                (None, None) => None,
+            };
+            Some((res, fragment))
+        });
 
         // Cache only if resolved successfully - don't silence duplicate errors
         if let Some(res) = res {
@@ -1529,103 +1347,55 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
-    ) -> Option<(Res, Option<UrlFragment>)> {
+    ) -> Option<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
         let item_id = key.item_id;
         let base_node = key.module_id;
-        let extra_fragment = &key.extra_fragment;
 
         match disambiguator.map(Disambiguator::ns) {
-            Some(expected_ns @ (ValueNS | TypeNS)) => {
-                match self.resolve(path_str, expected_ns, item_id, base_node, extra_fragment) {
+            Some(expected_ns) => {
+                match self.resolve(path_str, expected_ns, item_id, base_node) {
                     Ok(res) => Some(res),
-                    Err(ErrorKind::Resolve(box mut kind)) => {
+                    Err(err) => {
                         // We only looked in one namespace. Try to give a better error if possible.
-                        if kind.full_res().is_none() {
-                            let other_ns = if expected_ns == ValueNS { TypeNS } else { ValueNS };
-                            // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`
-                            // See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach
-                            for new_ns in [other_ns, MacroNS] {
-                                if let Some(res) = self.check_full_res(
-                                    new_ns,
-                                    path_str,
-                                    item_id,
-                                    base_node,
-                                    extra_fragment,
-                                ) {
-                                    kind = ResolutionFailure::WrongNamespace { res, expected_ns };
+                        // FIXME: really it should be `resolution_failure` that does this, not `resolve_with_disambiguator`.
+                        // See https://github.com/rust-lang/rust/pull/76955#discussion_r493953382 for a good approach.
+                        let mut err = ResolutionFailure::NotResolved(err);
+                        for other_ns in [TypeNS, ValueNS, MacroNS] {
+                            if other_ns != expected_ns {
+                                if let Ok(res) =
+                                    self.resolve(path_str, other_ns, item_id, base_node)
+                                {
+                                    err = ResolutionFailure::WrongNamespace {
+                                        res: full_res(self.cx.tcx, res),
+                                        expected_ns,
+                                    };
                                     break;
                                 }
                             }
                         }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![kind]);
-                        // This could just be a normal link or a broken link
-                        // we could potentially check if something is
-                        // "intra-doc-link-like" and warn in that case.
-                        None
-                    }
-                    Err(ErrorKind::AnchorFailure(msg)) => {
-                        anchor_failure(self.cx, diag, msg);
-                        None
+                        resolution_failure(self, diag, path_str, disambiguator, smallvec![err])
                     }
                 }
             }
             None => {
                 // Try everything!
-                let mut candidates = PerNS {
-                    macro_ns: self
-                        .resolve_macro(path_str, item_id, base_node)
-                        .map(|res| (res, extra_fragment.clone().map(UrlFragment::UserWritten))),
-                    type_ns: match self.resolve(
-                        path_str,
-                        TypeNS,
-                        item_id,
-                        base_node,
-                        extra_fragment,
-                    ) {
-                        Ok(res) => {
-                            debug!("got res in TypeNS: {:?}", res);
-                            Ok(res)
-                        }
-                        Err(ErrorKind::AnchorFailure(msg)) => {
-                            anchor_failure(self.cx, diag, msg);
-                            return None;
-                        }
-                        Err(ErrorKind::Resolve(box kind)) => Err(kind),
-                    },
-                    value_ns: match self.resolve(
-                        path_str,
-                        ValueNS,
-                        item_id,
-                        base_node,
-                        extra_fragment,
-                    ) {
-                        Ok(res) => Ok(res),
-                        Err(ErrorKind::AnchorFailure(msg)) => {
-                            anchor_failure(self.cx, diag, msg);
-                            return None;
-                        }
-                        Err(ErrorKind::Resolve(box kind)) => Err(kind),
-                    }
-                    .and_then(|(res, fragment)| {
-                        // Constructors are picked up in the type namespace.
+                let mut candidate = |ns| {
+                    self.resolve(path_str, ns, item_id, base_node)
+                        .map_err(ResolutionFailure::NotResolved)
+                };
+
+                let candidates = PerNS {
+                    macro_ns: candidate(MacroNS),
+                    type_ns: candidate(TypeNS),
+                    value_ns: candidate(ValueNS).and_then(|(res, def_id)| {
                         match res {
+                            // Constructors are picked up in the type namespace.
                             Res::Def(DefKind::Ctor(..), _) => {
                                 Err(ResolutionFailure::WrongNamespace { res, expected_ns: TypeNS })
                             }
-                            _ => {
-                                match (fragment, extra_fragment.clone()) {
-                                    (Some(fragment), Some(_)) => {
-                                        // Shouldn't happen but who knows?
-                                        Ok((res, Some(fragment)))
-                                    }
-                                    (fragment, None) => Ok((res, fragment)),
-                                    (None, fragment) => {
-                                        Ok((res, fragment.map(UrlFragment::UserWritten)))
-                                    }
-                                }
-                            }
+                            _ => Ok((res, def_id)),
                         }
                     }),
                 };
@@ -1633,15 +1403,13 @@ impl LinkCollector<'_, '_> {
                 let len = candidates.iter().filter(|res| res.is_ok()).count();
 
                 if len == 0 {
-                    resolution_failure(
+                    return resolution_failure(
                         self,
                         diag,
                         path_str,
                         disambiguator,
                         candidates.into_iter().filter_map(|res| res.err()).collect(),
                     );
-                    // this could just be a normal link
-                    return None;
                 }
 
                 if len == 1 {
@@ -1649,38 +1417,17 @@ impl LinkCollector<'_, '_> {
                 } else if len == 2 && is_derive_trait_collision(&candidates) {
                     Some(candidates.type_ns.unwrap())
                 } else {
-                    if is_derive_trait_collision(&candidates) {
-                        candidates.macro_ns = Err(ResolutionFailure::Dummy);
-                    }
+                    let ignore_macro = is_derive_trait_collision(&candidates);
                     // If we're reporting an ambiguity, don't mention the namespaces that failed
-                    let candidates = candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
+                    let mut candidates =
+                        candidates.map(|candidate| candidate.ok().map(|(res, _)| res));
+                    if ignore_macro {
+                        candidates.macro_ns = None;
+                    }
                     ambiguity_error(self.cx, diag, path_str, candidates.present_items().collect());
                     None
                 }
             }
-            Some(MacroNS) => {
-                match self.resolve_macro(path_str, item_id, base_node) {
-                    Ok(res) => Some((res, extra_fragment.clone().map(UrlFragment::UserWritten))),
-                    Err(mut kind) => {
-                        // `resolve_macro` only looks in the macro namespace. Try to give a better error if possible.
-                        for ns in [TypeNS, ValueNS] {
-                            if let Some(res) = self.check_full_res(
-                                ns,
-                                path_str,
-                                item_id,
-                                base_node,
-                                extra_fragment,
-                            ) {
-                                kind =
-                                    ResolutionFailure::WrongNamespace { res, expected_ns: MacroNS };
-                                break;
-                            }
-                        }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![kind]);
-                        None
-                    }
-                }
-            }
         }
     }
 }
@@ -1968,8 +1715,9 @@ fn resolution_failure(
     path_str: &str,
     disambiguator: Option<Disambiguator>,
     kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
-) {
+) -> Option<(Res, Option<DefId>)> {
     let tcx = collector.cx.tcx;
+    let mut recovered_res = None;
     report_diagnostic(
         tcx,
         BROKEN_INTRA_DOC_LINKS,
@@ -1995,12 +1743,12 @@ fn resolution_failure(
                 }
                 variants_seen.push(variant);
 
-                if let ResolutionFailure::NotResolved {
+                if let ResolutionFailure::NotResolved(UnresolvedPath {
                     item_id,
                     module_id,
                     partial_res,
                     unresolved,
-                } = &mut failure
+                }) = &mut failure
                 {
                     use DefKind::*;
 
@@ -2026,11 +1774,9 @@ fn resolution_failure(
                         };
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
-                            if let Some(res) =
-                                collector.check_full_res(ns, start, item_id, module_id, &None)
-                            {
+                            if let Ok(res) = collector.resolve(start, ns, item_id, module_id) {
                                 debug!("found partial_res={:?}", res);
-                                *partial_res = Some(res);
+                                *partial_res = Some(full_res(collector.cx.tcx, res));
                                 *unresolved = end.into();
                                 break 'outer;
                             }
@@ -2059,11 +1805,22 @@ fn resolution_failure(
                             diag.note(&note);
                         }
 
-                        // If the link has `::` in it, assume it was meant to be an intra-doc link.
-                        // Otherwise, the `[]` might be unrelated.
-                        // FIXME: don't show this for autolinks (`<>`), `()` style links, or reference links
                         if !path_str.contains("::") {
-                            diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
+                            if disambiguator.map_or(true, |d| d.ns() == MacroNS)
+                                && let Some(&res) = collector.cx.resolver_caches.all_macro_rules
+                                                             .get(&Symbol::intern(path_str))
+                            {
+                                diag.note(format!(
+                                    "`macro_rules` named `{path_str}` exists in this crate, \
+                                     but it is not in scope at this link's location"
+                                ));
+                                recovered_res = res.try_into().ok().map(|res| (res, None));
+                            } else {
+                                // If the link has `::` in it, assume it was meant to be an
+                                // intra-doc link. Otherwise, the `[]` might be unrelated.
+                                diag.help("to escape `[` and `]` characters, \
+                                           add '\\' before them like `\\[` or `\\]`");
+                            }
                         }
 
                         continue;
@@ -2130,7 +1887,6 @@ fn resolution_failure(
                 }
                 let note = match failure {
                     ResolutionFailure::NotResolved { .. } => unreachable!("handled above"),
-                    ResolutionFailure::Dummy => continue,
                     ResolutionFailure::WrongNamespace { res, expected_ns } => {
                         suggest_disambiguator(res, diag, path_str, diag_info.ori_link, sp);
 
@@ -2140,38 +1896,6 @@ fn resolution_failure(
                             expected_ns.descr()
                         )
                     }
-                    ResolutionFailure::NoParentItem => {
-                        // FIXME(eddyb) this doesn't belong here, whatever made
-                        // the `ResolutionFailure::NoParentItem` should emit an
-                        // immediate or delayed `span_bug` about the issue.
-                        tcx.sess.delay_span_bug(
-                            sp.unwrap_or(DUMMY_SP),
-                            "intra-doc link missing parent item",
-                        );
-
-                        "BUG: all intra-doc links should have a parent item".to_owned()
-                    }
-                    ResolutionFailure::MalformedGenerics(variant) => match variant {
-                        MalformedGenerics::UnbalancedAngleBrackets => {
-                            String::from("unbalanced angle brackets")
-                        }
-                        MalformedGenerics::MissingType => {
-                            String::from("missing type for generic parameters")
-                        }
-                        MalformedGenerics::HasFullyQualifiedSyntax => {
-                            diag.note("see https://github.com/rust-lang/rust/issues/74563 for more information");
-                            String::from("fully-qualified syntax is unsupported")
-                        }
-                        MalformedGenerics::InvalidPathSeparator => {
-                            String::from("has invalid path separator")
-                        }
-                        MalformedGenerics::TooManyAngleBrackets => {
-                            String::from("too many angle brackets")
-                        }
-                        MalformedGenerics::EmptyAngleBrackets => {
-                            String::from("empty angle brackets")
-                        }
-                    },
                 };
                 if let Some(span) = sp {
                     diag.span_label(span, &note);
@@ -2181,24 +1905,28 @@ fn resolution_failure(
             }
         },
     );
+
+    recovered_res
 }
 
-/// Report an anchor failure.
-fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: AnchorFailure) {
-    let (msg, anchor_idx) = match failure {
-        AnchorFailure::MultipleAnchors => {
-            (format!("`{}` contains multiple anchors", diag_info.ori_link), 1)
-        }
-        AnchorFailure::RustdocAnchorConflict(res) => (
-            format!(
-                "`{}` contains an anchor, but links to {kind}s are already anchored",
-                diag_info.ori_link,
-                kind = res.descr(),
-            ),
-            0,
-        ),
-    };
+fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
+    let msg = format!("`{}` contains multiple anchors", diag_info.ori_link);
+    anchor_failure(cx, diag_info, &msg, 1)
+}
 
+fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, res: Res) {
+    let (link, kind) = (diag_info.ori_link, res.descr());
+    let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
+    anchor_failure(cx, diag_info, &msg, 0)
+}
+
+/// Report an anchor failure.
+fn anchor_failure(
+    cx: &DocContext<'_>,
+    diag_info: DiagnosticInfo<'_>,
+    msg: &str,
+    anchor_idx: usize,
+) {
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, &diag_info, |diag, sp| {
         if let Some(mut sp) = sp {
             if let Some((fragment_offset, _)) =
@@ -2208,13 +1936,6 @@ fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: A
             }
             diag.span_label(sp, "invalid anchor");
         }
-        if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure {
-            if let Some(sp) = sp {
-                span_bug!(sp, "anchors should be allowed now");
-            } else {
-                bug!("anchors should be allowed now");
-            }
-        }
     });
 }
 
@@ -2235,6 +1956,40 @@ fn disambiguator_error(
     });
 }
 
+fn report_malformed_generics(
+    cx: &DocContext<'_>,
+    diag_info: DiagnosticInfo<'_>,
+    err: MalformedGenerics,
+    path_str: &str,
+) {
+    report_diagnostic(
+        cx.tcx,
+        BROKEN_INTRA_DOC_LINKS,
+        &format!("unresolved link to `{}`", path_str),
+        &diag_info,
+        |diag, sp| {
+            let note = match err {
+                MalformedGenerics::UnbalancedAngleBrackets => "unbalanced angle brackets",
+                MalformedGenerics::MissingType => "missing type for generic parameters",
+                MalformedGenerics::HasFullyQualifiedSyntax => {
+                    diag.note(
+                        "see https://github.com/rust-lang/rust/issues/74563 for more information",
+                    );
+                    "fully-qualified syntax is unsupported"
+                }
+                MalformedGenerics::InvalidPathSeparator => "has invalid path separator",
+                MalformedGenerics::TooManyAngleBrackets => "too many angle brackets",
+                MalformedGenerics::EmptyAngleBrackets => "empty angle brackets",
+            };
+            if let Some(span) = sp {
+                diag.span_label(span, note);
+            } else {
+                diag.note(note);
+            }
+        },
+    );
+}
+
 /// Report an ambiguity error, where there were multiple possible resolutions.
 fn ambiguity_error(
     cx: &DocContext<'_>,
@@ -2331,17 +2086,6 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
     });
 }
 
-/// Given an enum variant's res, return the res of its enum and the associated fragment.
-fn handle_variant(
-    cx: &DocContext<'_>,
-    res: Res,
-) -> Result<(Res, Option<ItemFragment>), ErrorKind<'static>> {
-    let parent = cx.tcx.parent(res.def_id(cx.tcx));
-    let parent_def = Res::Def(DefKind::Enum, parent);
-    let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
-    Ok((parent_def, Some(ItemFragment(FragmentKind::Variant, variant.def_id))))
-}
-
 /// Resolve a primitive type or value.
 fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
     if ns != TypeNS {
@@ -2381,7 +2125,7 @@ fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
     Some(Res::Primitive(prim))
 }
 
-fn strip_generics_from_path(path_str: &str) -> Result<String, ResolutionFailure<'static>> {
+fn strip_generics_from_path(path_str: &str) -> Result<String, MalformedGenerics> {
     let mut stripped_segments = vec![];
     let mut path = path_str.chars().peekable();
     let mut segment = Vec::new();
@@ -2396,9 +2140,7 @@ fn strip_generics_from_path(path_str: &str) -> Result<String, ResolutionFailure<
                         stripped_segments.push(stripped_segment);
                     }
                 } else {
-                    return Err(ResolutionFailure::MalformedGenerics(
-                        MalformedGenerics::InvalidPathSeparator,
-                    ));
+                    return Err(MalformedGenerics::InvalidPathSeparator);
                 }
             }
             '<' => {
@@ -2406,14 +2148,10 @@ fn strip_generics_from_path(path_str: &str) -> Result<String, ResolutionFailure<
 
                 match path.next() {
                     Some('<') => {
-                        return Err(ResolutionFailure::MalformedGenerics(
-                            MalformedGenerics::TooManyAngleBrackets,
-                        ));
+                        return Err(MalformedGenerics::TooManyAngleBrackets);
                     }
                     Some('>') => {
-                        return Err(ResolutionFailure::MalformedGenerics(
-                            MalformedGenerics::EmptyAngleBrackets,
-                        ));
+                        return Err(MalformedGenerics::EmptyAngleBrackets);
                     }
                     Some(chr) => {
                         segment.push(chr);
@@ -2441,16 +2179,10 @@ fn strip_generics_from_path(path_str: &str) -> Result<String, ResolutionFailure<
 
     let stripped_path = stripped_segments.join("::");
 
-    if !stripped_path.is_empty() {
-        Ok(stripped_path)
-    } else {
-        Err(ResolutionFailure::MalformedGenerics(MalformedGenerics::MissingType))
-    }
+    if !stripped_path.is_empty() { Ok(stripped_path) } else { Err(MalformedGenerics::MissingType) }
 }
 
-fn strip_generics_from_path_segment(
-    segment: Vec<char>,
-) -> Result<String, ResolutionFailure<'static>> {
+fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, MalformedGenerics> {
     let mut stripped_segment = String::new();
     let mut param_depth = 0;
 
@@ -2465,9 +2197,7 @@ fn strip_generics_from_path_segment(
             if latest_generics_chunk.contains(" as ") {
                 // The segment tries to use fully-qualified syntax, which is currently unsupported.
                 // Give a helpful error message instead of completely ignoring the angle brackets.
-                return Err(ResolutionFailure::MalformedGenerics(
-                    MalformedGenerics::HasFullyQualifiedSyntax,
-                ));
+                return Err(MalformedGenerics::HasFullyQualifiedSyntax);
             }
         } else {
             if param_depth == 0 {
@@ -2482,6 +2212,6 @@ fn strip_generics_from_path_segment(
         Ok(stripped_segment)
     } else {
         // The segment has unbalanced angle brackets, e.g. `Vec<T` or `Vec<T>>`
-        Err(ResolutionFailure::MalformedGenerics(MalformedGenerics::UnbalancedAngleBrackets))
+        Err(MalformedGenerics::UnbalancedAngleBrackets)
     }
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index 07d05cab1d1..6f9912e71c5 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -40,6 +40,7 @@ crate fn early_resolve_intra_doc_links(
         traits_in_scope: Default::default(),
         all_traits: Default::default(),
         all_trait_impls: Default::default(),
+        all_macro_rules: Default::default(),
         document_private_items,
     };
 
@@ -64,7 +65,7 @@ crate fn early_resolve_intra_doc_links(
         traits_in_scope: link_resolver.traits_in_scope,
         all_traits: Some(link_resolver.all_traits),
         all_trait_impls: Some(link_resolver.all_trait_impls),
-        all_macro_rules: link_resolver.resolver.take_all_macro_rules(),
+        all_macro_rules: link_resolver.all_macro_rules,
     }
 }
 
@@ -82,6 +83,7 @@ struct EarlyDocLinkResolver<'r, 'ra> {
     traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
     all_traits: Vec<DefId>,
     all_trait_impls: Vec<DefId>,
+    all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
     document_private_items: bool,
 }
 
@@ -134,24 +136,21 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
                 // using privacy, private traits and impls from other crates are never documented in
                 // the current crate, and links in their doc comments are not resolved.
                 for &def_id in &all_traits {
-                    if self.resolver.cstore().visibility_untracked(def_id) == Visibility::Public {
+                    if self.resolver.cstore().visibility_untracked(def_id).is_public() {
                         self.resolve_doc_links_extern_impl(def_id, false);
                     }
                 }
                 for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
-                    if self.resolver.cstore().visibility_untracked(trait_def_id)
-                        == Visibility::Public
+                    if self.resolver.cstore().visibility_untracked(trait_def_id).is_public()
                         && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| {
-                            self.resolver.cstore().visibility_untracked(ty_def_id)
-                                == Visibility::Public
+                            self.resolver.cstore().visibility_untracked(ty_def_id).is_public()
                         })
                     {
                         self.resolve_doc_links_extern_impl(impl_def_id, false);
                     }
                 }
                 for (ty_def_id, impl_def_id) in all_inherent_impls {
-                    if self.resolver.cstore().visibility_untracked(ty_def_id) == Visibility::Public
-                    {
+                    if self.resolver.cstore().visibility_untracked(ty_def_id).is_public() {
                         self.resolve_doc_links_extern_impl(impl_def_id, true);
                     }
                 }
@@ -173,35 +172,50 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
     }
 
     fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) {
-        self.resolve_doc_links_extern_outer(def_id, def_id);
+        self.resolve_doc_links_extern_outer_fixme(def_id, def_id);
         let assoc_item_def_ids = Vec::from_iter(
             self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess),
         );
         for assoc_def_id in assoc_item_def_ids {
-            if !is_inherent
-                || self.resolver.cstore().visibility_untracked(assoc_def_id) == Visibility::Public
+            if !is_inherent || self.resolver.cstore().visibility_untracked(assoc_def_id).is_public()
             {
-                self.resolve_doc_links_extern_outer(assoc_def_id, def_id);
+                self.resolve_doc_links_extern_outer_fixme(assoc_def_id, def_id);
             }
         }
     }
 
-    fn resolve_doc_links_extern_outer(&mut self, def_id: DefId, scope_id: DefId) {
+    // FIXME: replace all uses with `resolve_doc_links_extern_outer` to actually resolve links, not
+    // just add traits in scope. This may be expensive and require benchmarking and optimization.
+    fn resolve_doc_links_extern_outer_fixme(&mut self, def_id: DefId, scope_id: DefId) {
         if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
             return;
         }
-        // FIXME: actually resolve links, not just add traits in scope.
         if let Some(parent_id) = self.resolver.opt_parent(scope_id) {
             self.add_traits_in_scope(parent_id);
         }
     }
 
+    fn resolve_doc_links_extern_outer(&mut self, def_id: DefId, scope_id: DefId) {
+        if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
+            return;
+        }
+        let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess));
+        let parent_scope = ParentScope::module(
+            self.resolver.get_nearest_non_block_module(
+                self.resolver.opt_parent(scope_id).unwrap_or(scope_id),
+            ),
+            self.resolver,
+        );
+        self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope);
+    }
+
     fn resolve_doc_links_extern_inner(&mut self, def_id: DefId) {
         if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
             return;
         }
-        // FIXME: actually resolve links, not just add traits in scope.
-        self.add_traits_in_scope(def_id);
+        let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess));
+        let parent_scope = ParentScope::module(self.resolver.expect_module(def_id), self.resolver);
+        self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope);
     }
 
     fn resolve_doc_links_local(&mut self, attrs: &[ast::Attribute]) {
@@ -255,9 +269,16 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
                         }
                     }
 
-                    // FIXME: Resolve all prefixes for type-relative resolution or for diagnostics.
-                    if (need_assoc || !any_resolved) && pinfo.path_str.contains("::") {
-                        need_traits_in_scope = true;
+                    // Resolve all prefixes for type-relative resolution or for diagnostics.
+                    if need_assoc || !any_resolved {
+                        let mut path = &pinfo.path_str[..];
+                        while let Some(idx) = path.rfind("::") {
+                            path = &path[..idx];
+                            need_traits_in_scope = true;
+                            for ns in [TypeNS, ValueNS, MacroNS] {
+                                self.resolve_and_cache(path, ns, &parent_scope);
+                            }
+                        }
                     }
                 }
             }
@@ -279,7 +300,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
 
         for child in self.resolver.module_children_or_reexports(module_id) {
             // This condition should give a superset of `denied` from `fn clean_use_statement`.
-            if child.vis == Visibility::Public
+            if child.vis.is_public()
                 || self.document_private_items
                     && child.vis != Visibility::Restricted(module_id)
                     && module_id.is_local()
@@ -343,8 +364,10 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
                     self.all_trait_impls.push(self.resolver.local_def_id(item.id).to_def_id());
                 }
                 ItemKind::MacroDef(macro_def) if macro_def.macro_rules => {
-                    self.parent_scope.macro_rules =
+                    let (macro_rules_scope, res) =
                         self.resolver.macro_rules_scope(self.resolver.local_def_id(item.id));
+                    self.parent_scope.macro_rules = macro_rules_scope;
+                    self.all_macro_rules.insert(item.ident.name, res);
                 }
                 _ => {}
             }
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 0da490f3cd6..e0aed1e1ed4 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -303,7 +303,7 @@ crate fn run(
         // Run call-finder on all items
         let mut calls = FxHashMap::default();
         let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
-        tcx.hir().visit_all_item_likes(&mut finder.as_deep_visitor());
+        tcx.hir().deep_visit_all_item_likes(&mut finder);
 
         // Sort call locations within a given file in document order
         for fn_calls in calls.values_mut() {
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 17b3859a77b..eb2c8e5bae1 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -9,7 +9,7 @@ use std::path::PathBuf;
 use serde::{Deserialize, Serialize};
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 14;
+pub const FORMAT_VERSION: u32 = 15;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -391,6 +391,14 @@ pub enum WherePredicate {
         #[serde(rename = "type")]
         type_: Type,
         bounds: Vec<GenericBound>,
+        /// Used for Higher-Rank Trait Bounds (HRTBs)
+        /// ```plain
+        /// where for<'a> &'a T: Iterator,"
+        ///       ^^^^^^^
+        ///       |
+        ///       this part
+        /// ```
+        generic_params: Vec<GenericParamDef>,
     },
     RegionPredicate {
         lifetime: String,
@@ -408,7 +416,13 @@ pub enum GenericBound {
     TraitBound {
         #[serde(rename = "trait")]
         trait_: Type,
-        /// Used for HRTBs
+        /// Used for Higher-Rank Trait Bounds (HRTBs)
+        /// ```plain
+        /// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
+        ///          ^^^^^^^^^^^
+        ///          |
+        ///          this part
+        /// ```
         generic_params: Vec<GenericParamDef>,
         modifier: TraitBoundModifier,
     },
@@ -487,6 +501,13 @@ pub enum Type {
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct FunctionPointer {
     pub decl: FnDecl,
+    /// Used for Higher-Rank Trait Bounds (HRTBs)
+    /// ```plain
+    /// for<'c> fn(val: &'c i32) -> i32
+    /// ^^^^^^^
+    ///       |
+    ///       this part
+    /// ```
     pub generic_params: Vec<GenericParamDef>,
     pub header: Header,
 }
diff --git a/src/test/codegen/asm-clobber_abi.rs b/src/test/codegen/asm-clobber_abi.rs
index a87152e0321..f70caea2fb9 100644
--- a/src/test/codegen/asm-clobber_abi.rs
+++ b/src/test/codegen/asm-clobber_abi.rs
@@ -6,21 +6,21 @@
 use std::arch::asm;
 
 // CHECK-LABEL: @clobber_sysv64
-// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_sysv64() {
     asm!("", clobber_abi("sysv64"));
 }
 
 // CHECK-LABEL: @clobber_win64
-// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: ={ax},={cx},={dx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_win64() {
     asm!("", clobber_abi("win64"));
 }
 
 // CHECK-LABEL: @clobber_sysv64
-// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_sysv64_edx() {
     let foo: i32;
@@ -28,7 +28,7 @@ pub unsafe fn clobber_sysv64_edx() {
 }
 
 // CHECK-LABEL: @clobber_win64
-// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}
+// CHECK: =&{dx},={ax},={cx},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k0},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{tmm0},~{tmm1},~{tmm2},~{tmm3},~{tmm4},~{tmm5},~{tmm6},~{tmm7},~{dirflag},~{fpsr},~{flags},~{memory}
 #[no_mangle]
 pub unsafe fn clobber_win64_edx() {
     let foo: i32;
diff --git a/src/test/codegen/asm-target-clobbers.rs b/src/test/codegen/asm-target-clobbers.rs
index 8845cfbe767..ac30e18ec52 100644
--- a/src/test/codegen/asm-target-clobbers.rs
+++ b/src/test/codegen/asm-target-clobbers.rs
@@ -6,6 +6,13 @@
 
 use std::arch::asm;
 
+// CHECK-LABEL: @amx_clobber
+// base: call void asm sideeffect inteldialect "", "~{tmm0}"()
+#[no_mangle]
+pub unsafe fn amx_clobber() {
+    asm!("", out("tmm0") _, options(nostack, nomem, preserves_flags));
+}
+
 // CHECK-LABEL: @avx512_clobber
 // base: call void asm sideeffect inteldialect "", "~{xmm31}"()
 // avx512: call float asm sideeffect inteldialect "", "=&{xmm31}"()
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index b13d576295c..381f11ff1ef 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -22,7 +22,7 @@ fn main() {
 }
 
 // Here we check that local debuginfo is mapped correctly.
-// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd"
+// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: ""
 
 // And here that debuginfo from other crates are expanded to absolute paths.
 // CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: ""
diff --git a/src/test/codegen/simd-wide-sum.rs b/src/test/codegen/simd-wide-sum.rs
new file mode 100644
index 00000000000..fde9b0fcd8a
--- /dev/null
+++ b/src/test/codegen/simd-wide-sum.rs
@@ -0,0 +1,54 @@
+// compile-flags: -C opt-level=3 --edition=2021
+// only-x86_64
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+#![feature(portable_simd)]
+
+use std::simd::Simd;
+const N: usize = 8;
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_simd
+pub fn wider_reduce_simd(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    let x: Simd<u16, N> = x.cast();
+    x.reduce_sum()
+}
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_loop
+pub fn wider_reduce_loop(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    let mut sum = 0_u16;
+    for i in 0..N {
+        sum += u16::from(x[i]);
+    }
+    sum
+}
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_iter
+pub fn wider_reduce_iter(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    x.as_array().iter().copied().map(u16::from).sum()
+}
+
+// This iterator one is the most interesting, as it's the one
+// which used to not auto-vectorize due to a suboptimality in the
+// `<array::IntoIter as Iterator>::fold` implementation.
+
+#[no_mangle]
+// CHECK-LABEL: @wider_reduce_into_iter
+pub fn wider_reduce_into_iter(x: Simd<u8, N>) -> u16 {
+    // CHECK: zext <8 x i8>
+    // CHECK-SAME: to <8 x i16>
+    // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16>
+    x.to_array().into_iter().map(u16::from).sum()
+}
diff --git a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
index 398937a04c9..e817d5715a1 100644
--- a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
+++ b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs
@@ -1,22 +1,27 @@
 // compile-flags: -C panic=abort
 
-// Test that `nounwind` atributes are not applied to `C-unwind` extern functions
-// even when the code is compiled with `panic=abort`.
+// Test that `nounwind` atributes are also applied to extern `C-unwind` Rust functions
+// when the code is compiled with `panic=abort`.
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
 
-extern "C-unwind" {
-    fn may_unwind();
-}
-
-// CHECK: @rust_item_that_can_unwind() unnamed_addr #0
+// CHECK: @rust_item_that_can_unwind() unnamed_addr [[ATTR0:#[0-9]+]]
 #[no_mangle]
 pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() {
+    // CHECK: call void @_ZN4core9panicking15panic_no_unwind
     may_unwind();
 }
 
+extern "C-unwind" {
+    // CHECK: @may_unwind() unnamed_addr [[ATTR1:#[0-9]+]]
+    fn may_unwind();
+}
+
 // Now, make sure that the LLVM attributes for this functions are correct.  First, make
 // sure that the first item is correctly marked with the `nounwind` attribute:
 //
-// CHECK-NOT: attributes #0 = { {{.*}}nounwind{{.*}} }
+// CHECK: attributes [[ATTR0]] = { {{.*}}nounwind{{.*}} }
+//
+// Now, check that foreign item is correctly marked without the `nounwind` attribute.
+// CHECK-NOT: attributes [[ATTR1]] = { {{.*}}nounwind{{.*}} }
diff --git a/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
new file mode 100644
index 00000000000..44d722d6f9b
--- /dev/null
+++ b/src/test/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
@@ -0,0 +1,24 @@
+// MIR for `main` after AbortUnwindingCalls
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/asm_unwind_panic_abort.rs:12:11: 12:11
+    let _1: ();                          // in scope 0 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+        _1 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:9: 14:49
+    }
+
+    bb1: {
+        StorageDead(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:14:48: 14:49
+        _0 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:13:5: 15:6
+        return;                          // scope 0 at $DIR/asm_unwind_panic_abort.rs:16:2: 16:2
+    }
+
+    bb2 (cleanup): {
+        abort;                           // scope 0 at $DIR/asm_unwind_panic_abort.rs:12:1: 16:2
+    }
+}
diff --git a/src/test/mir-opt/asm_unwind_panic_abort.rs b/src/test/mir-opt/asm_unwind_panic_abort.rs
new file mode 100644
index 00000000000..8201d54348a
--- /dev/null
+++ b/src/test/mir-opt/asm_unwind_panic_abort.rs
@@ -0,0 +1,16 @@
+//! Tests that unwinding from an asm block is caught and forced to abort
+//! when `-C panic=abort`.
+
+// min-llvm-version: 13.0.0
+// only-x86_64
+// compile-flags: -C panic=abort
+// no-prefer-dynamic
+
+#![feature(asm_unwind)]
+
+// EMIT_MIR asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
+fn main() {
+    unsafe {
+        std::arch::asm!("", options(may_unwind));
+    }
+}
diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
index 86e6d9e756c..c3b82aa853c 100644
--- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -21,7 +21,7 @@ extern crate rustc_session;
 use rustc_borrowck::consumers::BodyWithBorrowckFacts;
 use rustc_driver::Compilation;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_interface::interface::Compiler;
 use rustc_interface::{Config, Queries};
 use rustc_middle::ty::query::query_values::mir_borrowck;
@@ -65,11 +65,34 @@ impl rustc_driver::Callbacks for CompilerCalls {
         queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
             // Collect definition ids of MIR bodies.
             let hir = tcx.hir();
-            let mut visitor = HirVisitor { bodies: Vec::new() };
-            hir.visit_all_item_likes(&mut visitor);
+            let mut bodies = Vec::new();
+
+            let crate_items = tcx.hir_crate_items(());
+            for id in crate_items.items() {
+                if matches!(tcx.def_kind(id.def_id), DefKind::Fn) {
+                    bodies.push(id.def_id);
+                }
+            }
+
+            for id in crate_items.trait_items() {
+                if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) {
+                    let trait_item = hir.trait_item(id);
+                    if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind {
+                        if let rustc_hir::TraitFn::Provided(_) = trait_fn {
+                            bodies.push(trait_item.def_id);
+                        }
+                    }
+                }
+            }
+
+            for id in crate_items.impl_items() {
+                if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) {
+                    bodies.push(id.def_id);
+                }
+            }
 
             // Trigger borrow checking of all bodies.
-            for def_id in visitor.bodies {
+            for def_id in bodies {
                 let _ = tcx.optimized_mir(def_id);
             }
 
@@ -121,35 +144,6 @@ fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tc
     original_mir_borrowck(tcx, def_id)
 }
 
-/// Visitor that collects all body definition ids mentioned in the program.
-struct HirVisitor {
-    bodies: Vec<LocalDefId>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for HirVisitor {
-    fn visit_item(&mut self, item: &rustc_hir::Item) {
-        if let rustc_hir::ItemKind::Fn(..) = item.kind {
-            self.bodies.push(item.def_id);
-        }
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &rustc_hir::TraitItem) {
-        if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind {
-            if let rustc_hir::TraitFn::Provided(_) = trait_fn {
-                self.bodies.push(trait_item.def_id);
-            }
-        }
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &rustc_hir::ImplItem) {
-        if let rustc_hir::ImplItemKind::Fn(..) = impl_item.kind {
-            self.bodies.push(impl_item.def_id);
-        }
-    }
-
-    fn visit_foreign_item(&mut self, _foreign_item: &rustc_hir::ForeignItem) {}
-}
-
 /// Pull MIR bodies stored in the thread-local.
 fn get_bodies<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<(String, BodyWithBorrowckFacts<'tcx>)> {
     MIR_BODIES.with(|state| {
diff --git a/src/test/run-make/remap-path-prefix-dwarf/Makefile b/src/test/run-make/remap-path-prefix-dwarf/Makefile
new file mode 100644
index 00000000000..561a343d60b
--- /dev/null
+++ b/src/test/run-make/remap-path-prefix-dwarf/Makefile
@@ -0,0 +1,77 @@
+# This test makes sure that --remap-path-prefix has the expected effects on paths in debuginfo.
+# It tests several cases, each of them has a detailed description attached to it.
+
+# ignore-windows
+
+SRC_DIR := $(abspath .)
+SRC_DIR_PARENT := $(abspath ..)
+
+-include ../../run-make-fulldeps/tools.mk
+
+all: \
+  abs_input_outside_working_dir \
+  rel_input_remap_working_dir \
+  rel_input_remap_working_dir_parent \
+  rel_input_remap_working_dir_child \
+  abs_input_inside_working_dir \
+  abs_input_outside_working_dir
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path *is* within
+# the working directory of the compiler. We are remapping the path that contains `src`.
+abs_input_inside_working_dir:
+	# We explicitly switch to a directory that *is* a prefix of the directory our
+	# source code is contained in.
+	cd $(SRC_DIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_inside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED
+	# We expect the path to the main source file to be remapped.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_inside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with an *ABSOLUTE PATH* as input, and that absolute path is *not* within
+# the working directory of the compiler. We are remapping both the path that contains `src` and
+# the working directory to the same thing. This setup corresponds to a workaround that is needed
+# when trying to remap everything to something that looks like a local path.
+# Relative paths are interpreted as relative to the compiler's working directory (e.g. in
+# debuginfo). If we also remap the working directory, the compiler strip it from other paths so
+# that the final outcome is the desired one again.
+abs_input_outside_working_dir:
+	# We explicitly switch to a directory that is *not* a prefix of the directory our
+	# source code is contained in.
+	cd $(TMPDIR) && $(RUSTC) $(SRC_DIR)/src/quux.rs -o "$(TMPDIR)/abs_input_outside_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix $(SRC_DIR)=REMAPPED --remap-path-prefix $(TMPDIR)=REMAPPED
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump $(TMPDIR)/abs_input_outside_working_dir.rlib | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping the working directory of
+# the compiler, which naturally is an implicit prefix of our relative input path. Debuginfo will
+# expand the relative path to an absolute path and we expect the working directory to be remapped
+# in that expansion.
+rel_input_remap_working_dir:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)=REMAPPED"
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) "REMAPPED/src/quux.rs"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *SUB-DIRECTORY* of the
+# compiler's working directory. This test makes sure that that directory is remapped even though it
+# won't actually show up in this form in the compiler's SourceMap and instead is only constructed
+# on demand during debuginfo generation.
+rel_input_remap_working_dir_child:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR)/src=REMAPPED"
+	# We expect `src/quux.rs` to have been remapped to `REMAPPED/quux.rs`.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) "REMAPPED/quux.rs"
+	# We don't want to find the path that we just remapped anywhere in the DWARF
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "$(SRC_DIR)/src"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_child.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
+
+# The compiler is called with a *RELATIVE PATH* as input. We are remapping a *PARENT DIRECTORY* of
+# the compiler's working directory.
+rel_input_remap_working_dir_parent:
+	cd $(SRC_DIR) && $(RUSTC) src/quux.rs -o "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" -Cdebuginfo=2 --remap-path-prefix "$(SRC_DIR_PARENT)=REMAPPED"
+	# We expect `src/quux.rs` to have been remapped to `REMAPPED/remap-path-prefix-dwarf/src/quux.rs`.
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) "REMAPPED/remap-path-prefix-dwarf/src/quux.rs"
+	# We don't want to find the path that we just remapped anywhere in the DWARF
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "$(SRC_DIR_PARENT)"
+	# No weird duplication of remapped components (see #78479)
+	"$(LLVM_BIN_DIR)"/llvm-dwarfdump "$(TMPDIR)/rel_input_remap_working_dir_parent.rlib" | $(CGREP) -v "REMAPPED/REMAPPED"
diff --git a/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs b/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs
new file mode 100644
index 00000000000..38d5ef6194c
--- /dev/null
+++ b/src/test/run-make/remap-path-prefix-dwarf/src/quux.rs
@@ -0,0 +1,5 @@
+#![crate_type = "rlib"]
+
+pub fn foo() {
+    println!("foo");
+}
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index aca8390dfb3..d0b3175114c 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -45,3 +45,37 @@ goto: file://|DOC_PATH|/test_docs/index.html?search=test&filter-crate=lib2
 wait-for: "#crate-search"
 assert-property: ("#crate-search", {"value": "lib2"})
 assert-false: "#results .externcrate"
+
+// Checking that the text for the "title" is correct (the "All" comes from the "<select>").
+assert-text: ("#search-settings", "Results for test in All", STARTS_WITH)
+
+// Checking the display of the crate filter.
+// We start with the light theme.
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+reload:
+
+timeout: 2000
+wait-for: "#crate-search"
+assert-css: ("#crate-search", {
+    "border": "1px solid rgb(224, 224, 224)",
+    "color": "rgb(0, 0, 0)",
+    "background-color": "rgb(255, 255, 255)",
+})
+
+// We now check the dark theme.
+click: "#settings-menu"
+wait-for: "#settings"
+click: "#theme-dark"
+wait-for-css: ("#crate-search", {
+    "border": "1px solid rgb(240, 240, 240)",
+    "color": "rgb(17, 17, 17)",
+    "background-color": "rgb(240, 240, 240)",
+})
+
+// And finally we check the ayu theme.
+click: "#theme-ayu"
+wait-for-css: ("#crate-search", {
+    "border": "1px solid rgb(66, 76, 87)",
+    "color": "rgb(197, 197, 197)",
+    "background-color": "rgb(20, 25, 32)",
+})
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index 18270264266..9a9c45a9b7f 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -5,36 +5,25 @@ assert-false: "#settings"
 // We now click on the settings button.
 click: "#settings-menu"
 wait-for: "#settings"
-assert: "#main-content.hidden"
 assert-css: ("#settings", {"display": "block"})
 // Let's close it by clicking on the same button.
 click: "#settings-menu"
-assert-false: "#alternative-display #settings"
-assert: "#not-displayed #settings"
-assert: "#main-content:not(.hidden)"
-
-// Let's open and then close it again with the "close settings" button.
-click: "#settings-menu"
-wait-for: "#alternative-display #settings"
-assert: "#main-content.hidden"
-click: "#back"
-wait-for: "#not-displayed #settings"
-assert: "#main-content:not(.hidden)"
+wait-for-css: ("#settings", {"display": "none"})
 
 // Let's check that pressing "ESCAPE" is closing it.
 click: "#settings-menu"
-wait-for: "#alternative-display #settings"
+wait-for-css: ("#settings", {"display": "block"})
 press-key: "Escape"
-wait-for: "#not-displayed #settings"
-assert: "#main-content:not(.hidden)"
+wait-for-css: ("#settings", {"display": "none"})
 
 // Let's click on it when the search results are displayed.
 focus: ".search-input"
 write: "test"
 wait-for: "#alternative-display #search"
 click: "#settings-menu"
-wait-for: "#alternative-display #settings"
-assert: "#not-displayed #search"
+wait-for-css: ("#settings", {"display": "block"})
+// Ensure that the search is still displayed.
+wait-for: "#alternative-display #search"
 assert: "#main-content.hidden"
 
 // Now let's check the content of the settings menu.
diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml
index 42d945d0eb8..37a7c166294 100644
--- a/src/test/rustdoc-gui/shortcuts.goml
+++ b/src/test/rustdoc-gui/shortcuts.goml
@@ -12,15 +12,3 @@ assert-css: ("#help", {"display": "flex"})
 assert-false: "#help.hidden"
 press-key: "Escape"
 assert-css: ("#help.hidden", {"display": "none"})
-// Check for the themes list.
-assert-css: ("#theme-choices", {"display": "none"})
-press-key: "t"
-assert-css: ("#theme-choices", {"display": "block"})
-press-key: "t"
-// We ensure that 't' hides back the menu.
-assert-css: ("#theme-choices", {"display": "none"})
-press-key: "t"
-assert-css: ("#theme-choices", {"display": "block"})
-press-key: "Escape"
-// We ensure that 'Escape' hides the menu too.
-assert-css: ("#theme-choices", {"display": "none"})
diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml
index 9706511ea19..fb1c37ae68e 100644
--- a/src/test/rustdoc-gui/theme-change.goml
+++ b/src/test/rustdoc-gui/theme-change.goml
@@ -1,12 +1,21 @@
 // Ensures that the theme change is working as expected.
 goto: file://|DOC_PATH|/test_docs/index.html
-click: "#theme-picker"
-click: "#theme-choices > button:first-child"
-// should be the ayu theme so let's check the color
+local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
+reload:
+click: "#settings-menu"
+wait-for: "#theme-ayu"
+click: "#theme-ayu"
+// should be the ayu theme so let's check the color.
 wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" })
-click: "#theme-choices > button:last-child"
-// should be the light theme so let's check the color
+assert-local-storage: { "rustdoc-theme": "ayu" }
+click: "#theme-light"
+// should be the light theme so let's check the color.
 wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+assert-local-storage: { "rustdoc-theme": "light" }
+click: "#theme-dark"
+// Should be the dark theme so let's check the color.
+wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" })
+assert-local-storage: { "rustdoc-theme": "dark" }
 
 goto: file://|DOC_PATH|/settings.html
 wait-for: "#settings"
diff --git a/src/test/rustdoc-json/fn_pointer/generics.rs b/src/test/rustdoc-json/fn_pointer/generics.rs
new file mode 100644
index 00000000000..646f720e663
--- /dev/null
+++ b/src/test/rustdoc-json/fn_pointer/generics.rs
@@ -0,0 +1,14 @@
+// ignore-tidy-linelength
+
+#![feature(no_core)]
+#![no_core]
+
+// @count generics.json "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"'
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\"
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }'
+// @count - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\"
+// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32;
diff --git a/src/test/rustdoc-json/fns/generic_args.rs b/src/test/rustdoc-json/fns/generic_args.rs
index 3b03724b040..69150443c29 100644
--- a/src/test/rustdoc-json/fns/generic_args.rs
+++ b/src/test/rustdoc-json/fns/generic_args.rs
@@ -6,6 +6,9 @@
 // @set foo = generic_args.json "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
+// @set generic_foo = generic_args.json "$.index[*][?(@.name=='GenericFoo')].id"
+pub trait GenericFoo<'a> {}
+
 // @is - "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]"
 // @count - "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1
 // @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
@@ -29,19 +32,40 @@ pub fn generics<F: Foo>(f: F) {}
 // @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
-// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 1
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"'
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-// @count - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 1
+// @count - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3
 // @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"'
 // @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"'
 // @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"'
-// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 1
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3
+
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
-pub fn where_clase<F>(f: F)
+
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.inner.id" $generic_foo
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]"
+
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
+// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+pub fn where_clase<F, G, H>(f: F, g: G, h: H)
 where
     F: Foo,
+    G: for<'a> GenericFoo<'a>,
+    for<'b> &'b H: Foo,
 {
 }
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs b/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs
index 84d63c20aa8..8490584c1b4 100644
--- a/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules-error.rs
@@ -10,12 +10,11 @@ mod no_escape {
     }
 }
 
-/// [before_but_limited_to_module] FIXME: This error should be reported
-// ERROR unresolved link to `before_but_limited_to_module`
-/// [after] FIXME: This error should be reported
-// ERROR unresolved link to `after`
-/// [str] FIXME: This error shouldn not be reported
-//~^ ERROR `str` is both a builtin type and a macro
+/// [before_but_limited_to_module]
+//~^ ERROR unresolved link to `before_but_limited_to_module`
+/// [after]
+//~^ ERROR unresolved link to `after`
+/// [str]
 fn check() {}
 
 macro_rules! after {
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
index 4b984f4f6c0..8e17323fdde 100644
--- a/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
@@ -1,22 +1,23 @@
-error: `str` is both a builtin type and a macro
-  --> $DIR/macro-rules-error.rs:17:6
+error: unresolved link to `before_but_limited_to_module`
+  --> $DIR/macro-rules-error.rs:13:6
    |
-LL | /// [str] FIXME: This error shouldn not be reported
-   |      ^^^ ambiguous link
+LL | /// [before_but_limited_to_module]
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `before_but_limited_to_module` in scope
    |
 note: the lint level is defined here
   --> $DIR/macro-rules-error.rs:5:9
    |
 LL | #![deny(rustdoc::broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: to link to the builtin type, prefix with `prim@`
+   = note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
+
+error: unresolved link to `after`
+  --> $DIR/macro-rules-error.rs:15:6
    |
-LL | /// [prim@str] FIXME: This error shouldn not be reported
-   |      +++++
-help: to link to the macro, add an exclamation mark
+LL | /// [after]
+   |      ^^^^^ no item named `after` in scope
    |
-LL | /// [str!] FIXME: This error shouldn not be reported
-   |         +
+   = note: `macro_rules` named `after` exists in this crate, but it is not in scope at this link's location
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/asm/generic-const.rs b/src/test/ui/asm/generic-const.rs
new file mode 100644
index 00000000000..55c5587804b
--- /dev/null
+++ b/src/test/ui/asm/generic-const.rs
@@ -0,0 +1,30 @@
+// needs-asm-support
+// build-pass
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::asm;
+
+fn foofoo<const N: usize>() {}
+
+unsafe fn foo<const N: usize>() {
+    asm!("/* {0} */", const N);
+    asm!("/* {0} */", const N + 1);
+    asm!("/* {0} */", sym foofoo::<N>);
+}
+
+fn barbar<T>() {}
+
+unsafe fn bar<T>() {
+    asm!("/* {0} */", const std::mem::size_of::<T>());
+    asm!("/* {0} */", const std::mem::size_of::<(T, T)>());
+    asm!("/* {0} */", sym barbar::<T>);
+    asm!("/* {0} */", sym barbar::<(T, T)>);
+}
+
+fn main() {
+    unsafe {
+        foo::<0>();
+        bar::<usize>();
+    }
+}
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
index 9f0121e11b4..367a035387b 100644
--- a/src/test/ui/asm/type-check-1.rs
+++ b/src/test/ui/asm/type-check-1.rs
@@ -63,7 +63,6 @@ fn main() {
 
 unsafe fn generic<T>() {
     asm!("{}", sym generic::<T>);
-    //~^ generic parameters may not be used in const operations
 }
 
 // Const operands must be integers and must be constants.
diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr
index 7dba69fb745..bf5ea1befb6 100644
--- a/src/test/ui/asm/type-check-1.stderr
+++ b/src/test/ui/asm/type-check-1.stderr
@@ -33,15 +33,6 @@ LL |         asm!("{}", sym x);
    |
    = help: `sym` operands must refer to either a function or a static
 
-error: generic parameters may not be used in const operations
-  --> $DIR/type-check-1.rs:65:30
-   |
-LL |     asm!("{}", sym generic::<T>);
-   |                              ^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
-
 error[E0308]: mismatched types
   --> $DIR/type-check-1.rs:55:26
    |
@@ -109,13 +100,13 @@ LL |         asm!("{}", inout(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:74:25
+  --> $DIR/type-check-1.rs:73:25
    |
 LL | global_asm!("{}", const 0f32);
    |                         ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:76:25
+  --> $DIR/type-check-1.rs:75:25
    |
 LL | global_asm!("{}", const 0 as *mut u8);
    |                         ^^^^^^^^^^^^ expected integer, found *-ptr
@@ -123,7 +114,7 @@ LL | global_asm!("{}", const 0 as *mut u8);
    = note:     expected type `{integer}`
            found raw pointer `*mut u8`
 
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0435.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr
index 9c29e969de8..a65f84ae58e 100644
--- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr
@@ -2,10 +2,18 @@ error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
   --> $DIR/hr-associated-type-projection-1.rs:13:33
    |
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-   |      - this type parameter      ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T`
+   |      - this type parameter      ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
    |
-   = note: expected associated type `<T as Deref>::Target`
-               found type parameter `T`
+   = note: expected type parameter `T`
+             found associated type `<T as Deref>::Target`
+note: required by a bound in `UnsafeCopy`
+  --> $DIR/hr-associated-type-projection-1.rs:3:64
+   |
+LL | trait UnsafeCopy<'a, T: Copy>
+   |       ---------- required by a bound in this
+LL | where
+LL |     for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
+   |                                                                ^^^^^^^^^^ required by this bound in `UnsafeCopy`
 help: consider further restricting this bound
    |
 LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<'_, T> for T {
diff --git a/src/test/ui/async-await/issue-73741-type-err-drop-tracking.rs b/src/test/ui/async-await/issue-73741-type-err-drop-tracking.rs
new file mode 100644
index 00000000000..c3423ad629f
--- /dev/null
+++ b/src/test/ui/async-await/issue-73741-type-err-drop-tracking.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// compile-flags: -Zdrop-tracking
+// Regression test for issue #73741
+// Ensures that we don't emit spurious errors when
+// a type error ocurrs in an `async fn`
+
+async fn weird() {
+    1 = 2; //~ ERROR invalid left-hand side
+
+    let mut loop_count = 0;
+    async {}.await
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-73741-type-err-drop-tracking.stderr b/src/test/ui/async-await/issue-73741-type-err-drop-tracking.stderr
new file mode 100644
index 00000000000..d4e3b6c3bf4
--- /dev/null
+++ b/src/test/ui/async-await/issue-73741-type-err-drop-tracking.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/issue-73741-type-err-drop-tracking.rs:8:7
+   |
+LL |     1 = 2;
+   |     - ^
+   |     |
+   |     cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr
index 95ee51a8826..68303b84208 100644
--- a/src/test/ui/binop/issue-77910-1.stderr
+++ b/src/test/ui/binop/issue-77910-1.stderr
@@ -12,20 +12,14 @@ LL |     assert_eq!(foo, y);
 error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
   --> $DIR/issue-77910-1.rs:8:5
    |
+LL | fn foo(s: &i32) -> &i32 {
+   |    --- consider calling this function
+...
 LL |     assert_eq!(foo, y);
    |     ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
-   = help: the following other types implement trait `Debug`:
-             extern "C" fn() -> Ret
-             extern "C" fn(A) -> Ret
-             extern "C" fn(A, ...) -> Ret
-             extern "C" fn(A, B) -> Ret
-             extern "C" fn(A, B, ...) -> Ret
-             extern "C" fn(A, B, C) -> Ret
-             extern "C" fn(A, B, C, ...) -> Ret
-             extern "C" fn(A, B, C, D) -> Ret
-           and 68 others
+   = help: use parentheses to call the function: `foo(s)`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
index b1e59e9d5de..e2b177b951c 100644
--- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
@@ -2,8 +2,13 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/builtin-superkinds-self-type.rs:10:16
    |
 LL | impl <T: Sync> Foo for T { }
-   |                ^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                ^^^ ...so that the type `T` will meet its required lifetime bounds...
    |
+note: ...that is required by this bound
+  --> $DIR/builtin-superkinds-self-type.rs:6:24
+   |
+LL | trait Foo : Sized+Sync+'static {
+   |                        ^^^^^^^
 help: consider adding an explicit lifetime bound...
    |
 LL | impl <T: Sync + 'static> Foo for T { }
diff --git a/src/test/ui/coherence/coherence-with-closure.rs b/src/test/ui/coherence/coherence-with-closure.rs
new file mode 100644
index 00000000000..6e3281d8508
--- /dev/null
+++ b/src/test/ui/coherence/coherence-with-closure.rs
@@ -0,0 +1,15 @@
+// Test that encountering closures during coherence does not cause issues.
+#![feature(type_alias_impl_trait)]
+type OpaqueClosure = impl Sized;
+fn defining_use() -> OpaqueClosure {
+    || ()
+}
+
+struct Wrapper<T>(T);
+trait Trait {}
+impl Trait for Wrapper<OpaqueClosure> {}
+//~^ ERROR cannot implement trait on type alias impl trait
+impl<T: Sync> Trait for Wrapper<T> {}
+//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-with-closure.stderr b/src/test/ui/coherence/coherence-with-closure.stderr
new file mode 100644
index 00000000000..20b986cee69
--- /dev/null
+++ b/src/test/ui/coherence/coherence-with-closure.stderr
@@ -0,0 +1,24 @@
+error: cannot implement trait on type alias impl trait
+  --> $DIR/coherence-with-closure.rs:10:24
+   |
+LL | impl Trait for Wrapper<OpaqueClosure> {}
+   |                        ^^^^^^^^^^^^^
+   |
+note: type alias impl trait defined here
+  --> $DIR/coherence-with-closure.rs:3:22
+   |
+LL | type OpaqueClosure = impl Sized;
+   |                      ^^^^^^^^^^
+
+error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
+  --> $DIR/coherence-with-closure.rs:12:1
+   |
+LL | impl Trait for Wrapper<OpaqueClosure> {}
+   | ------------------------------------- first implementation here
+LL |
+LL | impl<T: Sync> Trait for Wrapper<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/coherence/coherence-with-generator.rs b/src/test/ui/coherence/coherence-with-generator.rs
new file mode 100644
index 00000000000..d34c391db9f
--- /dev/null
+++ b/src/test/ui/coherence/coherence-with-generator.rs
@@ -0,0 +1,19 @@
+// Test that encountering closures during coherence does not cause issues.
+#![feature(type_alias_impl_trait, generators)]
+type OpaqueGenerator = impl Sized;
+fn defining_use() -> OpaqueGenerator {
+    || {
+        for i in 0..10 {
+            yield i;
+        }
+    }
+}
+
+struct Wrapper<T>(T);
+trait Trait {}
+impl Trait for Wrapper<OpaqueGenerator> {}
+//~^ ERROR cannot implement trait on type alias impl trait
+impl<T: Sync> Trait for Wrapper<T> {}
+//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-with-generator.stderr b/src/test/ui/coherence/coherence-with-generator.stderr
new file mode 100644
index 00000000000..249ad3cb9ec
--- /dev/null
+++ b/src/test/ui/coherence/coherence-with-generator.stderr
@@ -0,0 +1,24 @@
+error: cannot implement trait on type alias impl trait
+  --> $DIR/coherence-with-generator.rs:14:24
+   |
+LL | impl Trait for Wrapper<OpaqueGenerator> {}
+   |                        ^^^^^^^^^^^^^^^
+   |
+note: type alias impl trait defined here
+  --> $DIR/coherence-with-generator.rs:3:24
+   |
+LL | type OpaqueGenerator = impl Sized;
+   |                        ^^^^^^^^^^
+
+error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
+  --> $DIR/coherence-with-generator.rs:16:1
+   |
+LL | impl Trait for Wrapper<OpaqueGenerator> {}
+   | --------------------------------------- first implementation here
+LL |
+LL | impl<T: Sync> Trait for Wrapper<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/const-generics/issues/issue-88119.rs b/src/test/ui/const-generics/issues/issue-88119.rs
new file mode 100644
index 00000000000..70dfa7f708b
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-88119.rs
@@ -0,0 +1,35 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(const_trait_impl, generic_const_exprs)]
+
+trait ConstName {
+    const NAME_BYTES: &'static [u8];
+}
+
+impl const ConstName for u8 {
+    const NAME_BYTES: &'static [u8] = b"u8";
+}
+
+const fn name_len<T: ?Sized + ConstName>() -> usize {
+    T::NAME_BYTES.len()
+}
+
+impl<T: ?Sized + ConstName> const ConstName for &T
+where
+    [(); name_len::<T>()]:,
+{
+    const NAME_BYTES: &'static [u8] = b"&T";
+}
+
+impl<T: ?Sized + ConstName> const ConstName for &mut T
+where
+    [(); name_len::<T>()]:,
+{
+    const NAME_BYTES: &'static [u8] = b"&mut T";
+}
+
+pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES;
+pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES;
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
index 350bd941939..7873b3463c1 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
index 13a4fde0830..47349750111 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:18:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type Bar
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
diff --git a/src/test/ui/consts/const-fn-ptr.rs b/src/test/ui/consts/const-fn-ptr.rs
new file mode 100644
index 00000000000..b1befdf06af
--- /dev/null
+++ b/src/test/ui/consts/const-fn-ptr.rs
@@ -0,0 +1,16 @@
+const fn make_fn_ptr() -> fn() {
+    || {}
+}
+
+static STAT: () = make_fn_ptr()();
+//~^ ERROR function pointer
+
+const CONST: () = make_fn_ptr()();
+//~^ ERROR function pointer
+
+const fn call_ptr() {
+    make_fn_ptr()();
+    //~^ ERROR function pointer
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-fn-ptr.stderr b/src/test/ui/consts/const-fn-ptr.stderr
new file mode 100644
index 00000000000..84b02a25ec8
--- /dev/null
+++ b/src/test/ui/consts/const-fn-ptr.stderr
@@ -0,0 +1,20 @@
+error: function pointer calls are not allowed in statics
+  --> $DIR/const-fn-ptr.rs:5:19
+   |
+LL | static STAT: () = make_fn_ptr()();
+   |                   ^^^^^^^^^^^^^^^
+
+error: function pointer calls are not allowed in constants
+  --> $DIR/const-fn-ptr.rs:8:19
+   |
+LL | const CONST: () = make_fn_ptr()();
+   |                   ^^^^^^^^^^^^^^^
+
+error: function pointer calls are not allowed in constant functions
+  --> $DIR/const-fn-ptr.rs:12:5
+   |
+LL |     make_fn_ptr()();
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr
index b997aff0e83..3b80b3486a8 100644
--- a/src/test/ui/consts/issue-56164.stderr
+++ b/src/test/ui/consts/issue-56164.stderr
@@ -7,7 +7,7 @@ LL | const fn foo() { (||{})() }
    = note: closures need an RFC before allowed to be called in constant functions
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: function pointers are not allowed in const fn
+error: function pointer calls are not allowed in constant functions
   --> $DIR/issue-56164.rs:7:5
    |
 LL |     input()
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
index 22314160c5e..2beb531cc68 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
@@ -14,7 +14,7 @@ static CMP: () = {
 static PTR_INT_CAST: () = {
     let x = &0 as *const _ as usize;
     //~^ ERROR could not evaluate static initializer
-    //~| unable to turn pointer into raw bytes
+    //~| "exposing pointers" needs an rfc before being allowed inside constants
     let _v = x == x;
 };
 
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
index 2764d10348a..61d34e2e35d 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
@@ -8,7 +8,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ptr_arith.rs:15:13
    |
 LL |     let x = &0 as *const _ as usize;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ "exposing pointers" needs an rfc before being allowed inside constants
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/ptr_arith.rs:23:14
diff --git a/src/test/ui/consts/validate_never_arrays.32bit.stderr b/src/test/ui/consts/validate_never_arrays.32bit.stderr
index e2f5175bf0a..6280a7478e7 100644
--- a/src/test/ui/consts/validate_never_arrays.32bit.stderr
+++ b/src/test/ui/consts/validate_never_arrays.32bit.stderr
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:4:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type [!; 1]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 4, align: 4) {
diff --git a/src/test/ui/consts/validate_never_arrays.64bit.stderr b/src/test/ui/consts/validate_never_arrays.64bit.stderr
index c145eddef57..c5a71e5be51 100644
--- a/src/test/ui/consts/validate_never_arrays.64bit.stderr
+++ b/src/test/ui/consts/validate_never_arrays.64bit.stderr
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_never_arrays.rs:4:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type [!; 1]
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
diff --git a/src/test/ui/empty/empty-linkname.rs b/src/test/ui/empty/empty-linkname.rs
index b64123389c2..7113d913cd0 100644
--- a/src/test/ui/empty/empty-linkname.rs
+++ b/src/test/ui/empty/empty-linkname.rs
@@ -1,4 +1,4 @@
-#[link(name = "")] //~ ERROR: given with empty name
+#[link(name = "")] //~ ERROR: link name must not be empty
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/empty/empty-linkname.stderr b/src/test/ui/empty/empty-linkname.stderr
index b9d1841f16c..adcf3670d1d 100644
--- a/src/test/ui/empty/empty-linkname.stderr
+++ b/src/test/ui/empty/empty-linkname.stderr
@@ -1,8 +1,8 @@
-error[E0454]: `#[link(name = "")]` given with empty name
-  --> $DIR/empty-linkname.rs:1:1
+error[E0454]: link name must not be empty
+  --> $DIR/empty-linkname.rs:1:15
    |
 LL | #[link(name = "")]
-   | ^^^^^^^^^^^^^^^^^^ empty name given
+   |               ^^ empty link name
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0138.stderr b/src/test/ui/error-codes/E0138.stderr
index 2dc6976fe0e..fa8c3942732 100644
--- a/src/test/ui/error-codes/E0138.stderr
+++ b/src/test/ui/error-codes/E0138.stderr
@@ -2,10 +2,10 @@ error[E0138]: multiple `start` functions
   --> $DIR/E0138.rs:7:1
    |
 LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }
-   | ---------------------------------------------------------- previous `#[start]` function here
+   | ---------------------------------------------------- previous `#[start]` function here
 ...
 LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0454.stderr b/src/test/ui/error-codes/E0454.stderr
index 6b62bef112f..b9a506fee83 100644
--- a/src/test/ui/error-codes/E0454.stderr
+++ b/src/test/ui/error-codes/E0454.stderr
@@ -1,8 +1,8 @@
-error[E0454]: `#[link(name = "")]` given with empty name
-  --> $DIR/E0454.rs:1:1
+error[E0454]: link name must not be empty
+  --> $DIR/E0454.rs:1:15
    |
 LL | #[link(name = "")] extern "C" {}
-   | ^^^^^^^^^^^^^^^^^^ empty name given
+   |               ^^ empty link name
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0458.stderr b/src/test/ui/error-codes/E0458.stderr
index 0f2fec029e7..e641bba541e 100644
--- a/src/test/ui/error-codes/E0458.stderr
+++ b/src/test/ui/error-codes/E0458.stderr
@@ -1,12 +1,10 @@
-error[E0458]: unknown kind: `wonderful_unicorn`
-  --> $DIR/E0458.rs:1:8
+error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib
+  --> $DIR/E0458.rs:1:15
    |
 LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
-   | -------^^^^^^^^^^^^^^^^^^^^^^^^^^--
-   |        |
-   |        unknown kind
+   |               ^^^^^^^^^^^^^^^^^^^ unknown link kind
 
-error[E0459]: `#[link(...)]` specified without `name = "foo"`
+error[E0459]: `#[link]` attribute requires a `name = "string"` argument
   --> $DIR/E0458.rs:1:1
    |
 LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
diff --git a/src/test/ui/error-codes/E0459.stderr b/src/test/ui/error-codes/E0459.stderr
index 4e0d51e8753..8f0dd25e030 100644
--- a/src/test/ui/error-codes/E0459.stderr
+++ b/src/test/ui/error-codes/E0459.stderr
@@ -1,4 +1,4 @@
-error[E0459]: `#[link(...)]` specified without `name = "foo"`
+error[E0459]: `#[link]` attribute requires a `name = "string"` argument
   --> $DIR/E0459.rs:1:1
    |
 LL | #[link(kind = "dylib")] extern "C" {}
diff --git a/src/test/ui/error-codes/E0604.stderr b/src/test/ui/error-codes/E0604.stderr
index d715d28b73c..68da03928b7 100644
--- a/src/test/ui/error-codes/E0604.stderr
+++ b/src/test/ui/error-codes/E0604.stderr
@@ -2,13 +2,10 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/E0604.rs:2:5
    |
 LL |     1u32 as char;
-   |     ^^^^^^^^^^^^ invalid cast
-   |
-help: try `char::from_u32` instead
-  --> $DIR/E0604.rs:2:5
-   |
-LL |     1u32 as char;
    |     ^^^^^^^^^^^^
+   |     |
+   |     invalid cast
+   |     help: try `char::from_u32` instead: `char::from_u32(1u32)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 0ddb6fc99b0..81aa268cacc 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -57,13 +57,10 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:25:5
    |
 LL |     0u32 as char;
-   |     ^^^^^^^^^^^^ invalid cast
-   |
-help: try `char::from_u32` instead
-  --> $DIR/error-festival.rs:25:5
-   |
-LL |     0u32 as char;
    |     ^^^^^^^^^^^^
+   |     |
+   |     invalid cast
+   |     help: try `char::from_u32` instead: `char::from_u32(0u32)`
 
 error[E0605]: non-primitive cast: `u8` as `Vec<u8>`
   --> $DIR/error-festival.rs:29:5
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.rs b/src/test/ui/feature-gates/feature-gate-asm_const.rs
index d41d7b258aa..936918a3cfc 100644
--- a/src/test/ui/feature-gates/feature-gate-asm_const.rs
+++ b/src/test/ui/feature-gates/feature-gate-asm_const.rs
@@ -2,8 +2,14 @@
 
 use std::arch::asm;
 
+unsafe fn foo<const N: usize>() {
+    asm!("mov eax, {}", const N + 1);
+    //~^ ERROR const operands for inline assembly are unstable
+}
+
 fn main() {
     unsafe {
+        foo::<0>();
         asm!("mov eax, {}", const 123);
         //~^ ERROR const operands for inline assembly are unstable
     }
diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr
index 0202ccbe5a2..c248374ec49 100644
--- a/src/test/ui/feature-gates/feature-gate-asm_const.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm_const.stderr
@@ -1,5 +1,14 @@
 error[E0658]: const operands for inline assembly are unstable
-  --> $DIR/feature-gate-asm_const.rs:7:29
+  --> $DIR/feature-gate-asm_const.rs:6:25
+   |
+LL |     asm!("mov eax, {}", const N + 1);
+   |                         ^^^^^^^^^^^
+   |
+   = note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
+   = help: add `#![feature(asm_const)]` to the crate attributes to enable
+
+error[E0658]: const operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_const.rs:13:29
    |
 LL |         asm!("mov eax, {}", const 123);
    |                             ^^^^^^^^^
@@ -7,6 +16,6 @@ LL |         asm!("mov eax, {}", const 123);
    = note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
    = help: add `#![feature(asm_const)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs
index e4d781c6859..0de6b3abb18 100644
--- a/src/test/ui/feature-gates/feature-gate-asm_sym.rs
+++ b/src/test/ui/feature-gates/feature-gate-asm_sym.rs
@@ -2,9 +2,18 @@
 
 use std::arch::asm;
 
+fn bar<const N: usize>() {}
+
+fn foo<const N: usize>() {
+    unsafe {
+        asm!("mov eax, {}", sym bar::<N>);
+        //~^ ERROR sym operands for inline assembly are unstable
+    }
+}
+
 fn main() {
     unsafe {
-        asm!("mov eax, {}", sym main);
+        asm!("mov eax, {}", sym foo::<0>);
         //~^ ERROR sym operands for inline assembly are unstable
     }
 }
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
index 68f2d0f6c18..d4b16f60b0b 100644
--- a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
@@ -1,12 +1,21 @@
 error[E0658]: sym operands for inline assembly are unstable
-  --> $DIR/feature-gate-asm_sym.rs:7:29
+  --> $DIR/feature-gate-asm_sym.rs:9:29
    |
-LL |         asm!("mov eax, {}", sym main);
-   |                             ^^^^^^^^
+LL |         asm!("mov eax, {}", sym bar::<N>);
+   |                             ^^^^^^^^^^^^
    |
    = note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
    = help: add `#![feature(asm_sym)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: sym operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_sym.rs:16:29
+   |
+LL |         asm!("mov eax, {}", sym foo::<0>);
+   |                             ^^^^^^^^^^^^
+   |
+   = note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
+   = help: add `#![feature(asm_sym)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
index 41a7dfc3f37..8f47d596521 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
@@ -1,8 +1,8 @@
-error[E0658]: kind="link_cfg" is unstable
-  --> $DIR/feature-gate-link_cfg.rs:1:1
+error[E0658]: link cfg is unstable
+  --> $DIR/feature-gate-link_cfg.rs:1:22
    |
 LL | #[link(name = "foo", cfg(foo))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^^^^^^^
    |
    = note: see issue #37406 <https://github.com/rust-lang/rust/issues/37406> for more information
    = help: add `#![feature(link_cfg)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
index fedee812398..132bc6ab04a 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.rs
@@ -1,5 +1,5 @@
-#[link(name = "foo", modifiers = "+as-needed")]
-//~^ ERROR: `#[link(modifiers="as-needed")]` is unstable
+#[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
+//~^ ERROR: linking modifier `as-needed` is unstable
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr
index 96750aa6e80..2ef6a1c0404 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_as_needed.stderr
@@ -1,8 +1,8 @@
-error[E0658]: `#[link(modifiers="as-needed")]` is unstable
-  --> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:34
+error[E0658]: linking modifier `as-needed` is unstable
+  --> $DIR/feature-gate-native_link_modifiers_as_needed.rs:1:50
    |
-LL | #[link(name = "foo", modifiers = "+as-needed")]
-   |                                  ^^^^^^^^^^^^
+LL | #[link(name = "foo", kind = "dylib", modifiers = "+as-needed")]
+   |                                                  ^^^^^^^^^^^^
    |
    = note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
    = help: add `#![feature(native_link_modifiers_as_needed)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr
index 900605c3b37..743bcc9a1b3 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle-3.stderr
@@ -1,2 +1,2 @@
-error: bundle linking modifier is currently unstable and only accepted on the nightly compiler
+error: linking modifier `bundle` is unstable and only accepted on the nightly compiler
 
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs
index c3c3cff17c4..c1d5a31aaa4 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.rs
@@ -1,5 +1,5 @@
-#[link(name = "foo", modifiers = "+bundle")]
-//~^ ERROR: `#[link(modifiers="bundle")]` is unstable
+#[link(name = "foo", kind = "static", modifiers = "+bundle")]
+//~^ ERROR: linking modifier `bundle` is unstable
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr
index 984b90d9b6c..dcaa7fcc64f 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_bundle.stderr
@@ -1,8 +1,8 @@
-error[E0658]: `#[link(modifiers="bundle")]` is unstable
-  --> $DIR/feature-gate-native_link_modifiers_bundle.rs:1:34
+error[E0658]: linking modifier `bundle` is unstable
+  --> $DIR/feature-gate-native_link_modifiers_bundle.rs:1:51
    |
-LL | #[link(name = "foo", modifiers = "+bundle")]
-   |                                  ^^^^^^^^^
+LL | #[link(name = "foo", kind = "static", modifiers = "+bundle")]
+   |                                                   ^^^^^^^^^
    |
    = note: see issue #81490 <https://github.com/rust-lang/rust/issues/81490> for more information
    = help: add `#![feature(native_link_modifiers_bundle)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs
index 57527be1112..7b09195dc3f 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.rs
@@ -1,5 +1,5 @@
 #[link(name = "foo", modifiers = "+verbatim")]
-//~^ ERROR: `#[link(modifiers="verbatim")]` is unstable
+//~^ ERROR: linking modifier `verbatim` is unstable
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr
index 5c64c0d21bd..3bfbeb8db35 100644
--- a/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr
+++ b/src/test/ui/feature-gates/feature-gate-native_link_modifiers_verbatim.stderr
@@ -1,4 +1,4 @@
-error[E0658]: `#[link(modifiers="verbatim")]` is unstable
+error[E0658]: linking modifier `verbatim` is unstable
   --> $DIR/feature-gate-native_link_modifiers_verbatim.rs:1:34
    |
 LL | #[link(name = "foo", modifiers = "+verbatim")]
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs
index 995d9ced480..f894f517b38 100644
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib.rs
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs
@@ -1,6 +1,6 @@
 // only-windows
 #[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: kind="raw-dylib" is unstable
+//~^ ERROR: link kind `raw-dylib` is unstable
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
index bb64af38b2c..ca7a61f6413 100644
--- a/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr
@@ -1,8 +1,8 @@
-error[E0658]: kind="raw-dylib" is unstable
-  --> $DIR/feature-gate-raw-dylib.rs:2:1
+error[E0658]: link kind `raw-dylib` is unstable
+  --> $DIR/feature-gate-raw-dylib.rs:2:29
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^
    |
    = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
    = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr
index 76c317f7410..782d9e39456 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle-2.stderr
@@ -1,2 +1,2 @@
-warning: library kind `static-nobundle` has been superseded by specifying `-bundle` on library kind `static`. Try `static:-bundle`
+warning: library kind `static-nobundle` has been superseded by specifying modifier `-bundle` with library kind `static`. Try `static:-bundle`
 
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
index e4bfe8e8e05..50f1b7ff3fc 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.rs
@@ -1,6 +1,6 @@
 #[link(name = "foo", kind = "static-nobundle")]
-//~^ WARNING: library kind `static-nobundle` has been superseded by specifying modifier `-bundle` with library kind `static`
-//~^^ ERROR: kind="static-nobundle" is unstable
+//~^ WARNING: link kind `static-nobundle` has been superseded by specifying modifier `-bundle` with link kind `static`
+//~^^ ERROR: link kind `static-nobundle` is unstable
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
index eaf2e0db511..094661aeb57 100644
--- a/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
+++ b/src/test/ui/feature-gates/feature-gate-static-nobundle.stderr
@@ -1,14 +1,14 @@
-warning: library kind `static-nobundle` has been superseded by specifying modifier `-bundle` with library kind `static`
-  --> $DIR/feature-gate-static-nobundle.rs:1:22
+warning: link kind `static-nobundle` has been superseded by specifying modifier `-bundle` with link kind `static`
+  --> $DIR/feature-gate-static-nobundle.rs:1:29
    |
 LL | #[link(name = "foo", kind = "static-nobundle")]
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^^^^^^^
 
-error[E0658]: kind="static-nobundle" is unstable
-  --> $DIR/feature-gate-static-nobundle.rs:1:22
+error[E0658]: link kind `static-nobundle` is unstable
+  --> $DIR/feature-gate-static-nobundle.rs:1:29
    |
 LL | #[link(name = "foo", kind = "static-nobundle")]
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^^^^^^^
    |
    = note: see issue #37403 <https://github.com/rust-lang/rust/issues/37403> for more information
    = help: add `#![feature(static_nobundle)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr b/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr
index bc13a5d7d7b..93afa78459d 100644
--- a/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr
+++ b/src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr
@@ -1,4 +1,4 @@
-error[E0658]: trait upcasting coercion is experimental
+error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
   --> $DIR/feature-gate-trait_upcasting.rs:11:25
    |
 LL |     let foo: &dyn Foo = bar;
@@ -6,6 +6,7 @@ LL |     let foo: &dyn Foo = bar;
    |
    = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
    = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: required when coercing `&dyn Bar` into `&dyn Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index b0e295178c8..d8d2eca570e 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -581,6 +581,10 @@ mod link {
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
+
+    #[link()] extern "Rust" {}
+    //~^ WARN attribute should be applied to an `extern` block
+    //~| WARN this was previously accepted
 }
 
 struct StructForDeprecated;
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 2431957e539..cf9f89d8fde 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -310,7 +310,7 @@ LL | | }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:554:1
    |
 LL |   #[link()]
@@ -328,55 +328,55 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:601:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:1
    |
 LL | #[windows_subsystem = "windows"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:1
    |
 LL | #[no_builtins]
    | ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:735:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -407,7 +407,7 @@ LL | #![cold]
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
 LL | #![link()]
@@ -863,7 +863,7 @@ LL |     #[link_section = "1800"] impl S { }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:560:17
    |
 LL |     mod inner { #![link()] }
@@ -871,7 +871,7 @@ LL |     mod inner { #![link()] }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:565:5
    |
 LL |     #[link()] fn f() { }
@@ -879,7 +879,7 @@ LL |     #[link()] fn f() { }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:570:5
    |
 LL |     #[link()] struct S;
@@ -887,7 +887,7 @@ LL |     #[link()] struct S;
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:575:5
    |
 LL |     #[link()] type T = S;
@@ -895,7 +895,7 @@ LL |     #[link()] type T = S;
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to an `extern` block
+warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:580:5
    |
 LL |     #[link()] impl S { }
@@ -903,260 +903,268 @@ LL |     #[link()] impl S { }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
+warning: attribute should be applied to an `extern` block with non-Rust ABI
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:585:5
+   |
+LL |     #[link()] extern "Rust" {}
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
 warning: `#[must_use]` has no effect when applied to a module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:607:17
    |
 LL |     mod inner { #![must_use] }
    |                 ^^^^^^^^^^^^
 
 warning: `#[must_use]` has no effect when applied to a type alias
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:609:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:613:5
    |
 LL |     #[must_use] type T = S;
    |     ^^^^^^^^^^^
 
 warning: `#[must_use]` has no effect when applied to an item
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:5
    |
 LL |     #[must_use] impl S { }
    |     ^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:621:17
    |
 LL |     mod inner { #![windows_subsystem="windows"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
    |
 LL |     #[windows_subsystem = "windows"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:5
    |
 LL |     #[windows_subsystem = "windows"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
    |
 LL |     #[windows_subsystem = "windows"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5
    |
 LL |     #[windows_subsystem = "windows"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:645:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:661:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:686:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:17
    |
 LL |     mod inner { #![no_builtins] }
    |                 ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5
    |
 LL |     #[no_builtins] fn f() { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5
    |
 LL |     #[no_builtins] struct S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5
    |
 LL |     #[no_builtins] type T = S;
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5
    |
 LL |     #[no_builtins] impl S { }
    |     ^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1169,5 +1177,5 @@ LL | #![feature(rust1)]
    |
    = note: `#[warn(stable_features)]` on by default
 
-warning: 172 warnings emitted
+warning: 173 warnings emitted
 
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
index 768d1c36619..4d38cb19e9b 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-56556.rs
@@ -11,3 +11,20 @@ where
 fn main() {
     foo::<Vec<u32>>(vec![]);
 }
+
+mod another {
+    use std::ops::Deref;
+
+    fn test<T, TDeref>()
+    where
+        T: Deref<Target = TDeref>,
+        TDeref: ?Sized,
+        for<'a> &'a TDeref: IntoIterator,
+        for<'a> <&'a TDeref as IntoIterator>::IntoIter: Clone,
+    {
+    }
+
+    fn main() {
+        test::<Vec<u8>, _>();
+    }
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs
new file mode 100644
index 00000000000..ffd6857d84a
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90875.rs
@@ -0,0 +1,31 @@
+// check-pass
+
+trait Variable<'a> {
+    type Type;
+}
+
+impl Variable<'_> for () {
+    type Type = ();
+}
+
+fn check<F, T>(_: F)
+where
+    F: Fn(T), // <- if removed, all fn_* then require type annotations
+    F: for<'a> Fn(<T as Variable<'a>>::Type),
+    T: for<'a> Variable<'a>,
+{
+}
+
+fn test(arg: impl Fn(())) {
+    fn fn_1(_: ()) {}
+    let fn_2 = |_: ()| ();
+    let fn_3 = |a| fn_1(a);
+    let fn_4 = arg;
+
+    check(fn_1); // Error
+    check(fn_2); // Ok
+    check(fn_3); // Ok
+    check(fn_4); // Error
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-54895.rs b/src/test/ui/impl-trait/issues/issue-54895.rs
index a70166e03a7..8d7a1d56f83 100644
--- a/src/test/ui/impl-trait/issues/issue-54895.rs
+++ b/src/test/ui/impl-trait/issues/issue-54895.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 trait Trait<'a> {
     type Out;
     fn call(&'a self) -> Self::Out;
@@ -15,6 +13,7 @@ impl<'a> Trait<'a> for X {
 }
 
 fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
     X(())
 }
 
diff --git a/src/test/ui/impl-trait/issues/issue-54895.stderr b/src/test/ui/impl-trait/issues/issue-54895.stderr
new file mode 100644
index 00000000000..7d22f027a6d
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-54895.stderr
@@ -0,0 +1,14 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-54895.rs:15:53
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                                                     ^^
+   |
+note: lifetime declared here
+  --> $DIR/issue-54895.rs:15:20
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                    ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr b/src/test/ui/impl-trait/issues/issue-67830.nll.stderr
deleted file mode 100644
index 17fbe046e3a..00000000000
--- a/src/test/ui/impl-trait/issues/issue-67830.nll.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-67830.rs:23:5
-   |
-LL |     Wrap(|a| Some(a).into_iter())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-67830.rs:23:5
-   |
-LL |     Wrap(|a| Some(a).into_iter())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/impl-trait/issues/issue-67830.rs b/src/test/ui/impl-trait/issues/issue-67830.rs
index a308d975b43..92f7e005dbf 100644
--- a/src/test/ui/impl-trait/issues/issue-67830.rs
+++ b/src/test/ui/impl-trait/issues/issue-67830.rs
@@ -19,7 +19,7 @@ where
 
 struct A;
 fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
-    //~^ ERROR implementation of `FnOnce` is not general enough
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
     Wrap(|a| Some(a).into_iter())
 }
 
diff --git a/src/test/ui/impl-trait/issues/issue-67830.stderr b/src/test/ui/impl-trait/issues/issue-67830.stderr
index 4c0490c721b..d3ea8cb0377 100644
--- a/src/test/ui/impl-trait/issues/issue-67830.stderr
+++ b/src/test/ui/impl-trait/issues/issue-67830.stderr
@@ -1,11 +1,14 @@
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-67830.rs:21:14
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-67830.rs:21:62
    |
 LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |                                                              ^^
    |
-   = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2`
+note: lifetime declared here
+  --> $DIR/issue-67830.rs:21:23
+   |
+LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
+   |                       ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr
deleted file mode 100644
index 66cffa9e36c..00000000000
--- a/src/test/ui/impl-trait/issues/issue-88236-2.nll.stderr
+++ /dev/null
@@ -1,55 +0,0 @@
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:17:5
-   |
-LL |     &()
-   |     ^^^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:17:5
-   |
-LL |     &()
-   |     ^^^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: lifetime may not live long enough
-  --> $DIR/issue-88236-2.rs:20:5
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                  -- lifetime `'b` defined here
-LL |     x
-   |     ^ returning this value requires that `'b` must outlive `'static`
-   |
-help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'b` lifetime bound
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b {
-   |                                                                                  ++++
-help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'b` lifetime bound
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a + 'b> {
-   |                                                                                 ++++
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:20:5
-   |
-LL |     x
-   |     ^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:20:5
-   |
-LL |     x
-   |     ^ implementation of `Hrtb` is not general enough
-   |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
-
-error: aborting due to 5 previous errors
-
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.rs b/src/test/ui/impl-trait/issues/issue-88236-2.rs
index af26a1f54c4..fde8a6704cc 100644
--- a/src/test/ui/impl-trait/issues/issue-88236-2.rs
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.rs
@@ -13,11 +13,16 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
 fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    &() //~^ ERROR implementation of `Hrtb` is not general enough
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    &()
 }
+
 fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    x //~^ ERROR implementation of `Hrtb` is not general enough
+    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    x
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-88236-2.stderr b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
index 9574b880f7d..8605d07abe9 100644
--- a/src/test/ui/impl-trait/issues/issue-88236-2.stderr
+++ b/src/test/ui/impl-trait/issues/issue-88236-2.stderr
@@ -1,20 +1,38 @@
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:16:38
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-88236-2.rs:15:61
+   |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+   |                                                             ^^
+   |
+note: lifetime declared here
+  --> $DIR/issue-88236-2.rs:15:28
+   |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+   |                            ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-88236-2.rs:18:80
    |
 LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
+   |                                                                                ^^
    |
-   = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`...
-   = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1`
+note: lifetime declared here
+  --> $DIR/issue-88236-2.rs:18:47
+   |
+LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                                               ^^
 
-error: implementation of `Hrtb` is not general enough
-  --> $DIR/issue-88236-2.rs:19:36
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-88236-2.rs:23:78
    |
 LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Hrtb` is not general enough
+   |                                                                              ^^
    |
-   = note: `Hrtb<'1>` would have to be implemented for the type `&()`, for any lifetime `'1`...
-   = note: ...but `Hrtb<'_>` is actually implemented for the type `&()`
+note: lifetime declared here
+  --> $DIR/issue-88236-2.rs:23:45
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                                             ^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/impl-trait/issues/issue-88236.rs b/src/test/ui/impl-trait/issues/issue-88236.rs
index 2ea35270a7e..36d12417354 100644
--- a/src/test/ui/impl-trait/issues/issue-88236.rs
+++ b/src/test/ui/impl-trait/issues/issue-88236.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 // this used to cause stack overflows
 
 trait Hrtb<'a> {
@@ -15,5 +13,6 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issues/issue-88236.stderr b/src/test/ui/impl-trait/issues/issue-88236.stderr
new file mode 100644
index 00000000000..7a4cc57b088
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-88236.stderr
@@ -0,0 +1,14 @@
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/issue-88236.rs:15:61
+   |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+   |                                                             ^^
+   |
+note: lifetime declared here
+  --> $DIR/issue-88236.rs:15:28
+   |
+LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
+   |                            ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.rs b/src/test/ui/impl-trait/nested-rpit-hrtb.rs
new file mode 100644
index 00000000000..abf6a7e956c
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-rpit-hrtb.rs
@@ -0,0 +1,64 @@
+// Test the interaction between rested RPIT and HRTB.
+
+trait Foo<'a> {
+    type Assoc;
+}
+
+impl Foo<'_> for () {
+    type Assoc = ();
+}
+
+// Alternative version of `Foo` whose impl uses `'a`.
+trait Bar<'a> {
+    type Assoc;
+}
+
+impl<'a> Bar<'a> for () {
+    type Assoc = &'a ();
+}
+
+trait Qux<'a> {}
+
+impl Qux<'_> for () {}
+
+// This is not supported.
+fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+// This is not supported.
+fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+
+// This should pass.
+fn one_hrtb_mention_fn_trait_param<'b>() -> impl for<'a> Foo<'a, Assoc = impl Qux<'b>> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'b> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
+
+// This should pass.
+fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {}
+
+// This should pass.
+fn two_htrb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Qux<'b>> {}
+
+// `'b` is not in scope for the outlives bound.
+fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+//~^ ERROR use of undeclared lifetime name `'b` [E0261]
+
+// This should pass.
+fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
+
+// `'b` is not in scope for the outlives bound.
+fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+//~^ ERROR use of undeclared lifetime name `'b` [E0261]
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/nested-rpit-hrtb.stderr b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr
new file mode 100644
index 00000000000..3dbe6ebadfb
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -0,0 +1,82 @@
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/nested-rpit-hrtb.rs:54:77
+   |
+LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                                                                             ^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL | fn two_htrb_outlives() -> impl for<'b, 'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                                    +++
+help: consider introducing lifetime `'b` here
+   |
+LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                     ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/nested-rpit-hrtb.rs:61:82
+   |
+LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                                                                                  ^^ undeclared lifetime
+   |
+help: consider making the bound lifetime-generic with a new `'b` lifetime
+   |
+LL | fn two_htrb_outlives_uses() -> impl for<'b, 'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                                         +++
+help: consider introducing lifetime `'b` here
+   |
+LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
+   |                          ++++
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/nested-rpit-hrtb.rs:25:69
+   |
+LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+   |                                                                     ^^
+   |
+note: lifetime declared here
+  --> $DIR/nested-rpit-hrtb.rs:25:36
+   |
+LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
+   |                                    ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/nested-rpit-hrtb.rs:29:68
+   |
+LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+   |                                                                    ^^
+   |
+note: lifetime declared here
+  --> $DIR/nested-rpit-hrtb.rs:29:39
+   |
+LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
+   |                                       ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/nested-rpit-hrtb.rs:32:74
+   |
+LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+   |                                                                          ^^
+   |
+note: lifetime declared here
+  --> $DIR/nested-rpit-hrtb.rs:32:41
+   |
+LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+   |                                         ^^
+
+error: higher kinded lifetime bounds on nested opaque types are not supported yet
+  --> $DIR/nested-rpit-hrtb.rs:35:73
+   |
+LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+   |                                                                         ^^
+   |
+note: lifetime declared here
+  --> $DIR/nested-rpit-hrtb.rs:35:44
+   |
+LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
+   |                                            ^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/imports/unused-imports-in-test-mode.rs b/src/test/ui/imports/unused-imports-in-test-mode.rs
new file mode 100644
index 00000000000..ed0bb65b3aa
--- /dev/null
+++ b/src/test/ui/imports/unused-imports-in-test-mode.rs
@@ -0,0 +1,84 @@
+// compile-flags: --test
+
+#![deny(unused_imports)]
+
+use std::io::BufRead; //~ ERROR unused import: `std::io::BufRead`
+
+fn a() {}
+fn b() {}
+
+mod test {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod tests {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod test_a {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod a_test {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod tests_a {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod a_tests {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod fastest_search {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+#[cfg(test)]
+mod test_has_attr {
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+mod test_has_no_attr {
+    #[cfg(test)]
+    use super::a;  //~ ERROR unused import: `super::a`
+
+    fn foo() {
+        use crate::b;  //~ ERROR unused import: `crate::b`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/unused-imports-in-test-mode.stderr b/src/test/ui/imports/unused-imports-in-test-mode.stderr
new file mode 100644
index 00000000000..1847abd64b4
--- /dev/null
+++ b/src/test/ui/imports/unused-imports-in-test-mode.stderr
@@ -0,0 +1,122 @@
+error: unused import: `std::io::BufRead`
+  --> $DIR/unused-imports-in-test-mode.rs:5:5
+   |
+LL | use std::io::BufRead;
+   |     ^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-imports-in-test-mode.rs:3:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:11:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:14:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:19:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:22:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:27:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:30:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:35:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:38:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:43:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:46:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:51:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:54:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:59:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:62:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:68:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:71:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: unused import: `super::a`
+  --> $DIR/unused-imports-in-test-mode.rs:77:9
+   |
+LL |     use super::a;
+   |         ^^^^^^^^
+
+error: unused import: `crate::b`
+  --> $DIR/unused-imports-in-test-mode.rs:80:13
+   |
+LL |         use crate::b;
+   |             ^^^^^^^^
+
+error: aborting due to 19 previous errors
+
diff --git a/src/test/ui/inference/issue-28935.rs b/src/test/ui/inference/issue-28935.rs
new file mode 100644
index 00000000000..872822dbd0f
--- /dev/null
+++ b/src/test/ui/inference/issue-28935.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+use std::cell::RefCell;
+
+pub fn f(v: Vec<RefCell<u8>>) {
+    let _t = &mut *v[0].borrow_mut();
+}
+
+fn main() {}
diff --git a/src/test/ui/inline-const/const-match-pat-generic.rs b/src/test/ui/inline-const/const-match-pat-generic.rs
index e1946467583..7c0d83516ea 100644
--- a/src/test/ui/inline-const/const-match-pat-generic.rs
+++ b/src/test/ui/inline-const/const-match-pat-generic.rs
@@ -6,7 +6,8 @@
 fn foo<const V: usize>() {
     match 0 {
         const { V } => {},
-        //~^ ERROR const parameters cannot be referenced in patterns [E0158]
+        //~^ ERROR constant pattern depends on a generic parameter
+        //~| ERROR constant pattern depends on a generic parameter
         _ => {},
     }
 }
diff --git a/src/test/ui/inline-const/const-match-pat-generic.stderr b/src/test/ui/inline-const/const-match-pat-generic.stderr
index ade200d99ba..77267f12fb1 100644
--- a/src/test/ui/inline-const/const-match-pat-generic.stderr
+++ b/src/test/ui/inline-const/const-match-pat-generic.stderr
@@ -1,21 +1,26 @@
-error[E0158]: const parameters cannot be referenced in patterns
+error: constant pattern depends on a generic parameter
   --> $DIR/const-match-pat-generic.rs:8:9
    |
 LL |         const { V } => {},
    |         ^^^^^^^^^^^
 
 error: constant pattern depends on a generic parameter
-  --> $DIR/const-match-pat-generic.rs:20:9
+  --> $DIR/const-match-pat-generic.rs:21:9
    |
 LL |         const { f(V) } => {},
    |         ^^^^^^^^^^^^^^
 
 error: constant pattern depends on a generic parameter
-  --> $DIR/const-match-pat-generic.rs:20:9
+  --> $DIR/const-match-pat-generic.rs:8:9
+   |
+LL |         const { V } => {},
+   |         ^^^^^^^^^^^
+
+error: constant pattern depends on a generic parameter
+  --> $DIR/const-match-pat-generic.rs:21:9
    |
 LL |         const { f(V) } => {},
    |         ^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0158`.
diff --git a/src/test/ui/issues/issue-11515.stderr b/src/test/ui/issues/issue-11515.stderr
index a70e7c416bc..17bfae2a4e4 100644
--- a/src/test/ui/issues/issue-11515.stderr
+++ b/src/test/ui/issues/issue-11515.stderr
@@ -1,4 +1,4 @@
-error[E0658]: trait upcasting coercion is experimental
+error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
   --> $DIR/issue-11515.rs:9:33
    |
 LL |     let test = box Test { func: closure };
@@ -6,6 +6,7 @@ LL |     let test = box Test { func: closure };
    |
    = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
    = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-43925.rs b/src/test/ui/issues/issue-43925.rs
index 73d17928251..1a210887154 100644
--- a/src/test/ui/issues/issue-43925.rs
+++ b/src/test/ui/issues/issue-43925.rs
@@ -1,4 +1,4 @@
-#[link(name = "foo", cfg("rlib"))] //~ ERROR invalid argument for `cfg(..)`
+#[link(name = "foo", cfg("rlib"))] //~ ERROR link cfg must have a single predicate argument
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43925.stderr b/src/test/ui/issues/issue-43925.stderr
index 7bf64dc693c..b0ad25063de 100644
--- a/src/test/ui/issues/issue-43925.stderr
+++ b/src/test/ui/issues/issue-43925.stderr
@@ -1,8 +1,8 @@
-error: invalid argument for `cfg(..)`
-  --> $DIR/issue-43925.rs:1:26
+error: link cfg must have a single predicate argument
+  --> $DIR/issue-43925.rs:1:22
    |
 LL | #[link(name = "foo", cfg("rlib"))]
-   |                          ^^^^^^
+   |                      ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-43926.rs b/src/test/ui/issues/issue-43926.rs
index 0171c12b1cc..6d3003552dc 100644
--- a/src/test/ui/issues/issue-43926.rs
+++ b/src/test/ui/issues/issue-43926.rs
@@ -1,4 +1,4 @@
-#[link(name = "foo", cfg())] //~ ERROR `cfg()` must have an argument
+#[link(name = "foo", cfg())] //~ ERROR link cfg must have a single predicate argument
 extern "C" {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43926.stderr b/src/test/ui/issues/issue-43926.stderr
index d83e9bd7ed4..f67f91a6bd3 100644
--- a/src/test/ui/issues/issue-43926.stderr
+++ b/src/test/ui/issues/issue-43926.stderr
@@ -1,4 +1,4 @@
-error: `cfg()` must have an argument
+error: link cfg must have a single predicate argument
   --> $DIR/issue-43926.rs:1:22
    |
 LL | #[link(name = "foo", cfg())]
diff --git a/src/test/ui/issues/issue-5239-1.stderr b/src/test/ui/issues/issue-5239-1.stderr
index b743f0df4b1..f53ddb95416 100644
--- a/src/test/ui/issues/issue-5239-1.stderr
+++ b/src/test/ui/issues/issue-5239-1.stderr
@@ -5,11 +5,6 @@ LL |     let x = |ref x: isize| { x += 1; };
    |                              -^^^^^
    |                              |
    |                              cannot use `+=` on type `&isize`
-   |
-help: `+=` can be used on `isize`, you can dereference `x`
-   |
-LL |     let x = |ref x: isize| { *x += 1; };
-   |                              +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/linkage-attr/bad-extern-link-attrs.rs b/src/test/ui/linkage-attr/bad-extern-link-attrs.rs
deleted file mode 100644
index 43fe8c11d7c..00000000000
--- a/src/test/ui/linkage-attr/bad-extern-link-attrs.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[link()] //~ ERROR: specified without `name =
-#[link(name = "")] //~ ERROR: with empty name
-#[link(name = "foo")]
-#[link(name = "foo", kind = "bar")] //~ ERROR: unknown kind
-extern "C" {}
-
-fn main() {}
diff --git a/src/test/ui/linkage-attr/bad-extern-link-attrs.stderr b/src/test/ui/linkage-attr/bad-extern-link-attrs.stderr
deleted file mode 100644
index 525c605a9cf..00000000000
--- a/src/test/ui/linkage-attr/bad-extern-link-attrs.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0459]: `#[link(...)]` specified without `name = "foo"`
-  --> $DIR/bad-extern-link-attrs.rs:1:1
-   |
-LL | #[link()]
-   | ^^^^^^^^^ missing `name` argument
-
-error[E0454]: `#[link(name = "")]` given with empty name
-  --> $DIR/bad-extern-link-attrs.rs:2:1
-   |
-LL | #[link(name = "")]
-   | ^^^^^^^^^^^^^^^^^^ empty name given
-
-error[E0458]: unknown kind: `bar`
-  --> $DIR/bad-extern-link-attrs.rs:4:22
-   |
-LL | #[link(name = "foo", kind = "bar")]
-   | ---------------------^^^^^^^^^^^^--
-   |                      |
-   |                      unknown kind
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0454, E0458, E0459.
-For more information about an error, try `rustc --explain E0454`.
diff --git a/src/test/ui/linkage-attr/link-attr-validation-early.rs b/src/test/ui/linkage-attr/link-attr-validation-early.rs
new file mode 100644
index 00000000000..b9a835fb5e9
--- /dev/null
+++ b/src/test/ui/linkage-attr/link-attr-validation-early.rs
@@ -0,0 +1,8 @@
+// Top-level ill-formed
+#[link] //~ ERROR attribute must be of the form
+        //~| WARN this was previously accepted
+#[link = "foo"] //~ ERROR attribute must be of the form
+                //~| WARN this was previously accepted
+extern "C" {}
+
+fn main() {}
diff --git a/src/test/ui/linkage-attr/link-attr-validation-early.stderr b/src/test/ui/linkage-attr/link-attr-validation-early.stderr
new file mode 100644
index 00000000000..d36601ed0b4
--- /dev/null
+++ b/src/test/ui/linkage-attr/link-attr-validation-early.stderr
@@ -0,0 +1,21 @@
+error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
+  --> $DIR/link-attr-validation-early.rs:2:1
+   |
+LL | #[link]
+   | ^^^^^^^
+   |
+   = note: `#[deny(ill_formed_attribute_input)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...")]`
+  --> $DIR/link-attr-validation-early.rs:4:1
+   |
+LL | #[link = "foo"]
+   | ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/linkage-attr/link-attr-validation-late.rs b/src/test/ui/linkage-attr/link-attr-validation-late.rs
new file mode 100644
index 00000000000..b454fbd0ed1
--- /dev/null
+++ b/src/test/ui/linkage-attr/link-attr-validation-late.rs
@@ -0,0 +1,40 @@
+#![feature(native_link_modifiers_verbatim)]
+#![feature(link_cfg)]
+
+// Top-level ill-formed
+#[link(name = "...", "literal")] //~ ERROR unexpected `#[link]` argument
+#[link(name = "...", unknown)] //~ ERROR unexpected `#[link]` argument
+extern "C" {}
+
+// Duplicate arguments
+#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments
+#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments
+#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments
+#[link(name = "...", cfg(FALSE), cfg(FALSE))] //~ ERROR multiple `cfg` arguments
+#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments
+extern "C" {}
+
+// Ill-formed arguments
+#[link(name)] //~ ERROR link name must be of the form `name = "string"`
+              //~| ERROR `#[link]` attribute requires a `name = "string"` argument
+#[link(name())] //~ ERROR link name must be of the form `name = "string"`
+              //~| ERROR `#[link]` attribute requires a `name = "string"` argument
+#[link(name = "...", kind)] //~ ERROR link kind must be of the form `kind = "string"`
+#[link(name = "...", kind())] //~ ERROR link kind must be of the form `kind = "string"`
+#[link(name = "...", modifiers)] //~ ERROR link modifiers must be of the form `modifiers = "string"`
+#[link(name = "...", modifiers())] //~ ERROR link modifiers must be of the form `modifiers = "string"`
+#[link(name = "...", cfg)] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
+#[link(name = "...", cfg = "literal")] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
+#[link(name = "...", cfg("literal"))] //~ ERROR link cfg must have a single predicate argument
+#[link(name = "...", wasm_import_module)] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
+#[link(name = "...", wasm_import_module())] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
+extern "C" {}
+
+// Basic modifier validation
+#[link(name = "...", modifiers = "")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
+#[link(name = "...", modifiers = "no-plus-minus")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
+#[link(name = "...", modifiers = "+unknown")] //~ ERROR unknown linking modifier `unknown`
+#[link(name = "...", modifiers = "+verbatim,+verbatim")] //~ ERROR multiple `verbatim` modifiers
+extern "C" {}
+
+fn main() {}
diff --git a/src/test/ui/linkage-attr/link-attr-validation-late.stderr b/src/test/ui/linkage-attr/link-attr-validation-late.stderr
new file mode 100644
index 00000000000..bb08f9a4c02
--- /dev/null
+++ b/src/test/ui/linkage-attr/link-attr-validation-late.stderr
@@ -0,0 +1,147 @@
+error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module
+  --> $DIR/link-attr-validation-late.rs:5:22
+   |
+LL | #[link(name = "...", "literal")]
+   |                      ^^^^^^^^^
+
+error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module
+  --> $DIR/link-attr-validation-late.rs:6:22
+   |
+LL | #[link(name = "...", unknown)]
+   |                      ^^^^^^^
+
+error: multiple `name` arguments in a single `#[link]` attribute
+  --> $DIR/link-attr-validation-late.rs:10:22
+   |
+LL | #[link(name = "foo", name = "bar")]
+   |                      ^^^^^^^^^^^^
+
+error: multiple `kind` arguments in a single `#[link]` attribute
+  --> $DIR/link-attr-validation-late.rs:11:38
+   |
+LL | #[link(name = "...", kind = "dylib", kind = "bar")]
+   |                                      ^^^^^^^^^^^^
+
+error: multiple `modifiers` arguments in a single `#[link]` attribute
+  --> $DIR/link-attr-validation-late.rs:12:47
+   |
+LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+   |                                               ^^^^^^^^^^^^^^^^^
+
+error: multiple `cfg` arguments in a single `#[link]` attribute
+  --> $DIR/link-attr-validation-late.rs:13:34
+   |
+LL | #[link(name = "...", cfg(FALSE), cfg(FALSE))]
+   |                                  ^^^^^^^^^^
+
+error: multiple `wasm_import_module` arguments in a single `#[link]` attribute
+  --> $DIR/link-attr-validation-late.rs:14:36
+   |
+LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: link name must be of the form `name = "string"`
+  --> $DIR/link-attr-validation-late.rs:18:8
+   |
+LL | #[link(name)]
+   |        ^^^^
+
+error[E0459]: `#[link]` attribute requires a `name = "string"` argument
+  --> $DIR/link-attr-validation-late.rs:18:1
+   |
+LL | #[link(name)]
+   | ^^^^^^^^^^^^^ missing `name` argument
+
+error: link name must be of the form `name = "string"`
+  --> $DIR/link-attr-validation-late.rs:20:8
+   |
+LL | #[link(name())]
+   |        ^^^^^^
+
+error[E0459]: `#[link]` attribute requires a `name = "string"` argument
+  --> $DIR/link-attr-validation-late.rs:20:1
+   |
+LL | #[link(name())]
+   | ^^^^^^^^^^^^^^^ missing `name` argument
+
+error: link kind must be of the form `kind = "string"`
+  --> $DIR/link-attr-validation-late.rs:22:22
+   |
+LL | #[link(name = "...", kind)]
+   |                      ^^^^
+
+error: link kind must be of the form `kind = "string"`
+  --> $DIR/link-attr-validation-late.rs:23:22
+   |
+LL | #[link(name = "...", kind())]
+   |                      ^^^^^^
+
+error: link modifiers must be of the form `modifiers = "string"`
+  --> $DIR/link-attr-validation-late.rs:24:22
+   |
+LL | #[link(name = "...", modifiers)]
+   |                      ^^^^^^^^^
+
+error: link modifiers must be of the form `modifiers = "string"`
+  --> $DIR/link-attr-validation-late.rs:25:22
+   |
+LL | #[link(name = "...", modifiers())]
+   |                      ^^^^^^^^^^^
+
+error: link cfg must be of the form `cfg(/* predicate */)`
+  --> $DIR/link-attr-validation-late.rs:26:22
+   |
+LL | #[link(name = "...", cfg)]
+   |                      ^^^
+
+error: link cfg must be of the form `cfg(/* predicate */)`
+  --> $DIR/link-attr-validation-late.rs:27:22
+   |
+LL | #[link(name = "...", cfg = "literal")]
+   |                      ^^^^^^^^^^^^^^^
+
+error: link cfg must have a single predicate argument
+  --> $DIR/link-attr-validation-late.rs:28:22
+   |
+LL | #[link(name = "...", cfg("literal"))]
+   |                      ^^^^^^^^^^^^^^
+
+error: wasm import module must be of the form `wasm_import_module = "string"`
+  --> $DIR/link-attr-validation-late.rs:29:22
+   |
+LL | #[link(name = "...", wasm_import_module)]
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error: wasm import module must be of the form `wasm_import_module = "string"`
+  --> $DIR/link-attr-validation-late.rs:30:22
+   |
+LL | #[link(name = "...", wasm_import_module())]
+   |                      ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+  --> $DIR/link-attr-validation-late.rs:34:34
+   |
+LL | #[link(name = "...", modifiers = "")]
+   |                                  ^^
+
+error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+  --> $DIR/link-attr-validation-late.rs:35:34
+   |
+LL | #[link(name = "...", modifiers = "no-plus-minus")]
+   |                                  ^^^^^^^^^^^^^^^
+
+error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed
+  --> $DIR/link-attr-validation-late.rs:36:34
+   |
+LL | #[link(name = "...", modifiers = "+unknown")]
+   |                                  ^^^^^^^^^^
+
+error: multiple `verbatim` modifiers in a single `modifiers` argument
+  --> $DIR/link-attr-validation-late.rs:37:34
+   |
+LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")]
+   |                                  ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
+
+For more information about this error, try `rustc --explain E0459`.
diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr
index 0058af9b79e..3d64b0a67a1 100644
--- a/src/test/ui/main-wrong-location.stderr
+++ b/src/test/ui/main-wrong-location.stderr
@@ -8,7 +8,7 @@ note: here is a function named `main`
   --> $DIR/main-wrong-location.rs:4:5
    |
 LL |     fn main() { }
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^
    = note: you have one or more functions named `main` not defined at the crate level
    = help: consider moving the `main` function definitions
 
diff --git a/src/test/ui/manual/manual-link-bad-form.rs b/src/test/ui/manual/manual-link-bad-form.rs
index 9d092ae6db4..bc9b6be0294 100644
--- a/src/test/ui/manual/manual-link-bad-form.rs
+++ b/src/test/ui/manual/manual-link-bad-form.rs
@@ -1,5 +1,5 @@
 // compile-flags:-l static=
-// error-pattern: empty library name given via `-l`
+// error-pattern: library name must not be empty
 
 fn main() {
 }
diff --git a/src/test/ui/manual/manual-link-bad-form.stderr b/src/test/ui/manual/manual-link-bad-form.stderr
index ed3c4c4fc4d..7fd7a1066b4 100644
--- a/src/test/ui/manual/manual-link-bad-form.stderr
+++ b/src/test/ui/manual/manual-link-bad-form.stderr
@@ -1,4 +1,2 @@
-error: empty library name given via `-l`
-
-error: aborting due to previous error
+error: library name must not be empty
 
diff --git a/src/test/ui/manual/manual-link-bad-kind.rs b/src/test/ui/manual/manual-link-bad-kind.rs
index 86830a599b5..d1609338db6 100644
--- a/src/test/ui/manual/manual-link-bad-kind.rs
+++ b/src/test/ui/manual/manual-link-bad-kind.rs
@@ -1,5 +1,5 @@
 // compile-flags:-l bar=foo
-// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static
+// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework
 
 fn main() {
 }
diff --git a/src/test/ui/manual/manual-link-bad-kind.stderr b/src/test/ui/manual/manual-link-bad-kind.stderr
index 03c33a97512..86146956699 100644
--- a/src/test/ui/manual/manual-link-bad-kind.stderr
+++ b/src/test/ui/manual/manual-link-bad-kind.stderr
@@ -1,2 +1,2 @@
-error: unknown library kind `bar`, expected one of dylib, framework, or static
+error: unknown library kind `bar`, expected one of: static, dylib, framework
 
diff --git a/src/test/ui/manual/manual-link-framework.rs b/src/test/ui/manual/manual-link-framework.rs
index 0474526fcc1..57c5966e960 100644
--- a/src/test/ui/manual/manual-link-framework.rs
+++ b/src/test/ui/manual/manual-link-framework.rs
@@ -1,7 +1,7 @@
 // ignore-macos
 // ignore-ios
 // compile-flags:-l framework=foo
-// error-pattern: native frameworks are only available on macOS targets
+// error-pattern: library kind `framework` is only supported on Apple targets
 
 fn main() {
 }
diff --git a/src/test/ui/manual/manual-link-framework.stderr b/src/test/ui/manual/manual-link-framework.stderr
index 3e8da8b2f93..de045d56c9c 100644
--- a/src/test/ui/manual/manual-link-framework.stderr
+++ b/src/test/ui/manual/manual-link-framework.stderr
@@ -1,4 +1,4 @@
-error: native frameworks are only available on macOS targets
+error: library kind `framework` is only supported on Apple targets
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.rs b/src/test/ui/manual/manual-link-unsupported-kind.rs
index 34814db593f..7a40186d504 100644
--- a/src/test/ui/manual/manual-link-unsupported-kind.rs
+++ b/src/test/ui/manual/manual-link-unsupported-kind.rs
@@ -1,5 +1,5 @@
 // compile-flags:-l raw-dylib=foo
-// error-pattern: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework
 
 fn main() {
 }
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.stderr b/src/test/ui/manual/manual-link-unsupported-kind.stderr
index acb4463cb04..4965c0af5f2 100644
--- a/src/test/ui/manual/manual-link-unsupported-kind.stderr
+++ b/src/test/ui/manual/manual-link-unsupported-kind.stderr
@@ -1,2 +1,2 @@
-error: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework
 
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
index 84220ea172a..3a508459cc0 100644
--- a/src/test/ui/mismatched_types/cast-rfc0401.stderr
+++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -98,13 +98,10 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:41:13
    |
 LL |     let _ = 0x61u32 as char;
-   |             ^^^^^^^^^^^^^^^ invalid cast
-   |
-help: try `char::from_u32` instead
-  --> $DIR/cast-rfc0401.rs:41:13
-   |
-LL |     let _ = 0x61u32 as char;
    |             ^^^^^^^^^^^^^^^
+   |             |
+   |             invalid cast
+   |             help: try `char::from_u32` instead: `char::from_u32(0x61u32)`
 
 error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:43:13
diff --git a/src/test/ui/native-library-link-flags/empty-kind-1.rs b/src/test/ui/native-library-link-flags/empty-kind-1.rs
index 6f93d38ca93..086d8cff957 100644
--- a/src/test/ui/native-library-link-flags/empty-kind-1.rs
+++ b/src/test/ui/native-library-link-flags/empty-kind-1.rs
@@ -1,6 +1,6 @@
 // Unspecified kind should fail with an error
 
 // compile-flags: -l =mylib
-// error-pattern: unknown library kind ``, expected one of dylib, framework, or static
+// error-pattern: unknown library kind ``, expected one of: static, dylib, framework
 
 fn main() {}
diff --git a/src/test/ui/native-library-link-flags/empty-kind-1.stderr b/src/test/ui/native-library-link-flags/empty-kind-1.stderr
index 2a4a82d538f..37846c0b06f 100644
--- a/src/test/ui/native-library-link-flags/empty-kind-1.stderr
+++ b/src/test/ui/native-library-link-flags/empty-kind-1.stderr
@@ -1,2 +1,2 @@
-error: unknown library kind ``, expected one of dylib, framework, or static
+error: unknown library kind ``, expected one of: static, dylib, framework
 
diff --git a/src/test/ui/native-library-link-flags/empty-kind-2.rs b/src/test/ui/native-library-link-flags/empty-kind-2.rs
index c0c35577057..45ec8ec85e3 100644
--- a/src/test/ui/native-library-link-flags/empty-kind-2.rs
+++ b/src/test/ui/native-library-link-flags/empty-kind-2.rs
@@ -1,6 +1,6 @@
 // Unspecified kind should fail with an error
 
 // compile-flags: -l :+bundle=mylib
-// error-pattern: unknown library kind ``, expected one of dylib, framework, or static
+// error-pattern: unknown library kind ``, expected one of: static, dylib, framework
 
 fn main() {}
diff --git a/src/test/ui/native-library-link-flags/empty-kind-2.stderr b/src/test/ui/native-library-link-flags/empty-kind-2.stderr
index 2a4a82d538f..37846c0b06f 100644
--- a/src/test/ui/native-library-link-flags/empty-kind-2.stderr
+++ b/src/test/ui/native-library-link-flags/empty-kind-2.stderr
@@ -1,2 +1,2 @@
-error: unknown library kind ``, expected one of dylib, framework, or static
+error: unknown library kind ``, expected one of: static, dylib, framework
 
diff --git a/src/test/ui/native-library-link-flags/modifiers-override-2.stderr b/src/test/ui/native-library-link-flags/modifiers-override-2.stderr
index 9200d7bfb0c..aa5b59c5b6f 100644
--- a/src/test/ui/native-library-link-flags/modifiers-override-2.stderr
+++ b/src/test/ui/native-library-link-flags/modifiers-override-2.stderr
@@ -1,2 +1,2 @@
-error: duplicating linking modifier is currently unstable and only accepted on the nightly compiler
+error: multiple `whole-archive` modifiers in a single `-l` option
 
diff --git a/src/test/ui/native-library-link-flags/modifiers-override.rs b/src/test/ui/native-library-link-flags/modifiers-override.rs
index f6d770559e6..3912ac9f13d 100644
--- a/src/test/ui/native-library-link-flags/modifiers-override.rs
+++ b/src/test/ui/native-library-link-flags/modifiers-override.rs
@@ -3,12 +3,13 @@
 #![feature(native_link_modifiers_bundle)]
 
 #[link(name = "foo")]
-#[link( //~ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
+#[link(
     name = "bar",
     kind = "static",
     modifiers = "+whole-archive,-whole-archive",
-    //~^ ERROR same modifier is used multiple times in a single `modifiers` argument
+    //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument
     modifiers = "+bundle"
+    //~^ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
 )]
 extern "C" {}
 //~^ ERROR overriding linking modifiers from command line is not supported
diff --git a/src/test/ui/native-library-link-flags/modifiers-override.stderr b/src/test/ui/native-library-link-flags/modifiers-override.stderr
index 8644d2382d2..55362910e71 100644
--- a/src/test/ui/native-library-link-flags/modifiers-override.stderr
+++ b/src/test/ui/native-library-link-flags/modifiers-override.stderr
@@ -1,29 +1,23 @@
-error: same modifier is used multiple times in a single `modifiers` argument
-  --> $DIR/modifiers-override.rs:9:5
+error: multiple `modifiers` arguments in a single `#[link]` attribute
+  --> $DIR/modifiers-override.rs:11:5
    |
-LL |     modifiers = "+whole-archive,-whole-archive",
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     modifiers = "+bundle"
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: multiple `modifiers` arguments in a single `#[link]` attribute
-  --> $DIR/modifiers-override.rs:6:1
+error: multiple `whole-archive` modifiers in a single `modifiers` argument
+  --> $DIR/modifiers-override.rs:9:17
    |
-LL | / #[link(
-LL | |     name = "bar",
-LL | |     kind = "static",
-LL | |     modifiers = "+whole-archive,-whole-archive",
-LL | |
-LL | |     modifiers = "+bundle"
-LL | | )]
-   | |__^
+LL |     modifiers = "+whole-archive,-whole-archive",
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: overriding linking modifiers from command line is not supported
-  --> $DIR/modifiers-override.rs:13:1
+  --> $DIR/modifiers-override.rs:14:1
    |
 LL | extern "C" {}
    | ^^^^^^^^^^^^^
 
 error: overriding linking modifiers from command line is not supported
-  --> $DIR/modifiers-override.rs:13:1
+  --> $DIR/modifiers-override.rs:14:1
    |
 LL | extern "C" {}
    | ^^^^^^^^^^^^^
diff --git a/src/test/ui/nll/issue-54779-anon-static-lifetime.rs b/src/test/ui/nll/issue-54779-anon-static-lifetime.rs
new file mode 100644
index 00000000000..4bb983dd358
--- /dev/null
+++ b/src/test/ui/nll/issue-54779-anon-static-lifetime.rs
@@ -0,0 +1,51 @@
+// Regression test for #54779, checks if the diagnostics are confusing.
+
+#![feature(nll)]
+
+trait DebugWith<Cx: ?Sized> {
+    fn debug_with<'me>(&'me self, cx: &'me Cx) -> DebugCxPair<'me, Self, Cx> {
+        DebugCxPair { value: self, cx }
+    }
+
+    fn fmt_with(&self, cx: &Cx, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
+}
+
+struct DebugCxPair<'me, Value: ?Sized, Cx: ?Sized>
+where
+    Value: DebugWith<Cx>,
+{
+    value: &'me Value,
+    cx: &'me Cx,
+}
+
+trait DebugContext {}
+
+struct Foo {
+    bar: Bar,
+}
+
+impl DebugWith<dyn DebugContext> for Foo {
+    fn fmt_with(
+        &self,
+        cx: &dyn DebugContext,
+        fmt: &mut std::fmt::Formatter<'_>,
+    ) -> std::fmt::Result {
+        let Foo { bar } = self;
+        bar.debug_with(cx); //~ ERROR: lifetime may not live long enough
+        Ok(())
+    }
+}
+
+struct Bar {}
+
+impl DebugWith<dyn DebugContext> for Bar {
+    fn fmt_with(
+        &self,
+        cx: &dyn DebugContext,
+        fmt: &mut std::fmt::Formatter<'_>,
+    ) -> std::fmt::Result {
+        Ok(())
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-54779-anon-static-lifetime.stderr b/src/test/ui/nll/issue-54779-anon-static-lifetime.stderr
new file mode 100644
index 00000000000..9dc9bdbab8d
--- /dev/null
+++ b/src/test/ui/nll/issue-54779-anon-static-lifetime.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-54779-anon-static-lifetime.rs:34:24
+   |
+LL |         cx: &dyn DebugContext,
+   |             - let's call the lifetime of this reference `'1`
+...
+LL |         bar.debug_with(cx);
+   |                        ^^ cast requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/osx-frameworks.rs b/src/test/ui/osx-frameworks.rs
index 31b853e24fe..958183ec0d7 100644
--- a/src/test/ui/osx-frameworks.rs
+++ b/src/test/ui/osx-frameworks.rs
@@ -2,6 +2,6 @@
 
 #[link(name = "foo", kind = "framework")]
 extern "C" {}
-//~^^ ERROR: native frameworks are only available on macOS
+//~^^ ERROR: link kind `framework` is only supported on Apple targets
 
 fn main() {}
diff --git a/src/test/ui/osx-frameworks.stderr b/src/test/ui/osx-frameworks.stderr
index f3532913423..e4a5c98dc5c 100644
--- a/src/test/ui/osx-frameworks.stderr
+++ b/src/test/ui/osx-frameworks.stderr
@@ -1,8 +1,8 @@
-error[E0455]: native frameworks are only available on macOS targets
-  --> $DIR/osx-frameworks.rs:3:1
+error[E0455]: link kind `framework` is only supported on Apple targets
+  --> $DIR/osx-frameworks.rs:3:29
    |
 LL | #[link(name = "foo", kind = "framework")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-81804.rs b/src/test/ui/parser/issue-81804.rs
new file mode 100644
index 00000000000..803bde11e20
--- /dev/null
+++ b/src/test/ui/parser/issue-81804.rs
@@ -0,0 +1,9 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected pattern, found `=`
+// error-pattern: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
+// error-pattern: expected item, found `]`
+
+fn main() {}
+
+fn p([=(}
diff --git a/src/test/ui/parser/issue-81804.stderr b/src/test/ui/parser/issue-81804.stderr
new file mode 100644
index 00000000000..19c4422c622
--- /dev/null
+++ b/src/test/ui/parser/issue-81804.stderr
@@ -0,0 +1,41 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-81804.rs:9:11
+   |
+LL | fn p([=(}
+   |     --    ^
+   |     ||
+   |     |unclosed delimiter
+   |     unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-81804.rs:9:11
+   |
+LL | fn p([=(}
+   |     --    ^
+   |     ||
+   |     |unclosed delimiter
+   |     unclosed delimiter
+
+error: expected pattern, found `=`
+  --> $DIR/issue-81804.rs:9:7
+   |
+LL | fn p([=(}
+   |       ^ expected pattern
+
+error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
+  --> $DIR/issue-81804.rs:9:8
+   |
+LL | fn p([=(}
+   |        ^ -^
+   |        | |
+   |        | help: `)` may belong here
+   |        unclosed delimiter
+
+error: expected item, found `]`
+  --> $DIR/issue-81804.rs:9:11
+   |
+LL | fn p([=(}
+   |           ^ expected item
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/privacy/auxiliary/ctor_aux.rs b/src/test/ui/privacy/auxiliary/ctor_aux.rs
new file mode 100644
index 00000000000..9c99cca9ae6
--- /dev/null
+++ b/src/test/ui/privacy/auxiliary/ctor_aux.rs
@@ -0,0 +1,25 @@
+// edition:2021
+//! Missing docs lint warns about undocumented exported items.
+//! Use the lint to additionally verify that items are reachable
+//! but not exported.
+#![allow(non_camel_case_types)]
+#![deny(missing_docs)]
+
+mod hidden {
+    pub struct s;
+    pub enum e { x, y, z }
+    pub use e::*;
+    impl s {
+        pub fn f(&self) {}
+    }
+    impl e {
+        pub fn g(&self) {}
+    }
+}
+// Hide all type definitions while reexporting their constructors:
+mod e {}
+mod x {}
+mod y {}
+mod z {}
+mod s {}
+pub use hidden::*;
diff --git a/src/test/ui/privacy/ctor.rs b/src/test/ui/privacy/ctor.rs
new file mode 100644
index 00000000000..0ec15d68ed3
--- /dev/null
+++ b/src/test/ui/privacy/ctor.rs
@@ -0,0 +1,16 @@
+// Verify that a type is considered reachable when its constructor is
+// reachable. The auxiliary library is constructed so that all types are
+// shadowed and cannot be named directly, while their constructors are
+// reexported. Regression test for issue #96934.
+//
+// aux-build:ctor_aux.rs
+// edition:2021
+// build-pass
+
+extern crate ctor_aux;
+
+fn main() {
+    ctor_aux::s.f();
+    ctor_aux::x.g();
+    ctor_aux::y.g();
+}
diff --git a/src/test/ui/rfc-1717-dllimport/rename-modifiers.rs b/src/test/ui/rfc-1717-dllimport/rename-modifiers.rs
new file mode 100644
index 00000000000..30f4db7180e
--- /dev/null
+++ b/src/test/ui/rfc-1717-dllimport/rename-modifiers.rs
@@ -0,0 +1,9 @@
+// compile-flags: -l dylib=foo:bar
+// error-pattern: overriding linking modifiers from command line is not supported
+
+#![feature(native_link_modifiers_as_needed)]
+
+#![crate_type = "lib"]
+
+#[link(name = "foo", kind = "dylib", modifiers = "-as-needed")]
+extern "C" {}
diff --git a/src/test/ui/rfc-1717-dllimport/rename-modifiers.stderr b/src/test/ui/rfc-1717-dllimport/rename-modifiers.stderr
new file mode 100644
index 00000000000..bee639bf26c
--- /dev/null
+++ b/src/test/ui/rfc-1717-dllimport/rename-modifiers.stderr
@@ -0,0 +1,8 @@
+error: overriding linking modifiers from command line is not supported
+  --> $DIR/rename-modifiers.rs:9:1
+   |
+LL | extern "C" {}
+   | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2294-if-let-guard/typeck.stderr b/src/test/ui/rfc-2294-if-let-guard/typeck.stderr
index fbb941ffd91..dd1f4826fe0 100644
--- a/src/test/ui/rfc-2294-if-let-guard/typeck.stderr
+++ b/src/test/ui/rfc-2294-if-let-guard/typeck.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/typeck.rs:9:22
    |
 LL |         Ok(x) if let Err(_) = x => {},
-   |                      ^^^^^^ expected enum `Option`, found enum `Result`
+   |                      ^^^^^^   - this expression has type `Option<bool>`
+   |                      |
+   |                      expected enum `Option`, found enum `Result`
    |
    = note: expected enum `Option<bool>`
               found enum `Result<_, _>`
@@ -11,7 +13,9 @@ error[E0308]: mismatched types
   --> $DIR/typeck.rs:11:22
    |
 LL |         Ok(x) if let 0 = x => {},
-   |                      ^ expected enum `Option`, found integer
+   |                      ^   - this expression has type `Option<bool>`
+   |                      |
+   |                      expected enum `Option`, found integer
    |
    = note: expected enum `Option<bool>`
               found type `{integer}`
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
index 7a5d7ac2934..5856b18aa16 100644
--- a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
@@ -3,5 +3,5 @@
 #![feature(raw_dylib)]
 //~^ WARNING: the feature `raw_dylib` is incomplete
 #[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
+//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets
 extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
index f3879b63f91..600aac81a35 100644
--- a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
@@ -7,11 +7,12 @@ LL | #![feature(raw_dylib)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
 
-error: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
-  --> $DIR/raw-dylib-windows-only.rs:5:1
+error[E0455]: link kind `raw-dylib` is only supported on Windows targets
+  --> $DIR/raw-dylib-windows-only.rs:5:29
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0455`.
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
index 0783f04dc9b..ba6af8f15fa 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
@@ -5,6 +5,7 @@ LL |     foo::<S>(s);
    |     ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S`
    |
    = help: the trait `Trait` is implemented for `&'a mut S`
+   = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S`
 note: required by a bound in `foo`
   --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20
    |
diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr
index 3bd98c76307..b3cb6dd0614 100644
--- a/src/test/ui/suggestions/mut-ref-reassignment.stderr
+++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr
@@ -8,7 +8,7 @@ LL |     opt = None;
    |
    = note: expected mutable reference `&mut Option<String>`
                            found enum `Option<_>`
-help: consider dereferencing here to assign to the mutable borrowed piece of memory
+help: consider dereferencing here to assign to the mutably borrowed value
    |
 LL |     *opt = None;
    |     +
@@ -34,7 +34,7 @@ LL |     opt = Some(String::new())
    |
    = note: expected mutable reference `&mut Option<String>`
                            found enum `Option<String>`
-help: consider dereferencing here to assign to the mutable borrowed piece of memory
+help: consider dereferencing here to assign to the mutably borrowed value
    |
 LL |     *opt = Some(String::new())
    |     +
diff --git a/src/test/ui/traits/assoc-type-in-superbad.stderr b/src/test/ui/traits/assoc-type-in-superbad.stderr
index cbdb6b96f46..f3694791417 100644
--- a/src/test/ui/traits/assoc-type-in-superbad.stderr
+++ b/src/test/ui/traits/assoc-type-in-superbad.stderr
@@ -2,7 +2,13 @@ error[E0271]: type mismatch resolving `<std::vec::IntoIter<i32> as Iterator>::It
   --> $DIR/assoc-type-in-superbad.rs:12:16
    |
 LL |     type Key = u32;
-   |                ^^^ expected `i32`, found `u32`
+   |                ^^^ expected `u32`, found `i32`
+   |
+note: required by a bound in `Foo`
+  --> $DIR/assoc-type-in-superbad.rs:7:25
+   |
+LL | pub trait Foo: Iterator<Item=<Self as Foo>::Key> {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/typeck/assign-non-lval-derefmut.fixed b/src/test/ui/typeck/assign-non-lval-derefmut.fixed
new file mode 100644
index 00000000000..0c23199af22
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-derefmut.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+fn main() {
+    let x = std::sync::Mutex::new(1usize);
+    *x.lock().unwrap() = 2;
+    //~^ ERROR invalid left-hand side of assignment
+    *x.lock().unwrap() += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+
+    let mut y = x.lock().unwrap();
+    *y = 2;
+    //~^ ERROR mismatched types
+    *y += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+}
diff --git a/src/test/ui/typeck/assign-non-lval-derefmut.rs b/src/test/ui/typeck/assign-non-lval-derefmut.rs
new file mode 100644
index 00000000000..ec1882f5271
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-derefmut.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+
+fn main() {
+    let x = std::sync::Mutex::new(1usize);
+    x.lock().unwrap() = 2;
+    //~^ ERROR invalid left-hand side of assignment
+    x.lock().unwrap() += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+
+    let mut y = x.lock().unwrap();
+    y = 2;
+    //~^ ERROR mismatched types
+    y += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+}
diff --git a/src/test/ui/typeck/assign-non-lval-derefmut.stderr b/src/test/ui/typeck/assign-non-lval-derefmut.stderr
new file mode 100644
index 00000000000..a6fcdfe21f4
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-derefmut.stderr
@@ -0,0 +1,58 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/assign-non-lval-derefmut.rs:5:23
+   |
+LL |     x.lock().unwrap() = 2;
+   |     ----------------- ^
+   |     |
+   |     cannot assign to this expression
+   |
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |     *x.lock().unwrap() = 2;
+   |     +
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+  --> $DIR/assign-non-lval-derefmut.rs:7:5
+   |
+LL |     x.lock().unwrap() += 1;
+   |     -----------------^^^^^
+   |     |
+   |     cannot use `+=` on type `MutexGuard<'_, usize>`
+   |
+help: `+=` can be used on `usize`, you can dereference `x.lock().unwrap()`
+   |
+LL |     *x.lock().unwrap() += 1;
+   |     +
+
+error[E0308]: mismatched types
+  --> $DIR/assign-non-lval-derefmut.rs:11:9
+   |
+LL |     let mut y = x.lock().unwrap();
+   |                 ----------------- expected due to this value
+LL |     y = 2;
+   |         ^ expected struct `MutexGuard`, found integer
+   |
+   = note: expected struct `MutexGuard<'_, usize>`
+                found type `{integer}`
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |     *y = 2;
+   |     +
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
+  --> $DIR/assign-non-lval-derefmut.rs:13:5
+   |
+LL |     y += 1;
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `MutexGuard<'_, usize>`
+   |
+help: `+=` can be used on `usize`, you can dereference `y`
+   |
+LL |     *y += 1;
+   |     +
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0070, E0308, E0368.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.fixed b/src/test/ui/typeck/assign-non-lval-mut-ref.fixed
new file mode 100644
index 00000000000..10c7b9dbfb3
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-mut-ref.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+
+fn main() {
+    let mut x = vec![1usize];
+    *x.last_mut().unwrap() = 2;
+    //~^ ERROR invalid left-hand side of assignment
+    *x.last_mut().unwrap() += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
+
+    let y = x.last_mut().unwrap();
+    *y = 2;
+    //~^ ERROR mismatched types
+    *y += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
+}
diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.rs b/src/test/ui/typeck/assign-non-lval-mut-ref.rs
new file mode 100644
index 00000000000..bceff0ef09d
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-mut-ref.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+
+fn main() {
+    let mut x = vec![1usize];
+    x.last_mut().unwrap() = 2;
+    //~^ ERROR invalid left-hand side of assignment
+    x.last_mut().unwrap() += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
+
+    let y = x.last_mut().unwrap();
+    y = 2;
+    //~^ ERROR mismatched types
+    y += 1;
+    //~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
+}
diff --git a/src/test/ui/typeck/assign-non-lval-mut-ref.stderr b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr
new file mode 100644
index 00000000000..be2e9fe95e8
--- /dev/null
+++ b/src/test/ui/typeck/assign-non-lval-mut-ref.stderr
@@ -0,0 +1,56 @@
+error[E0070]: invalid left-hand side of assignment
+  --> $DIR/assign-non-lval-mut-ref.rs:5:27
+   |
+LL |     x.last_mut().unwrap() = 2;
+   |     --------------------- ^
+   |     |
+   |     cannot assign to this expression
+   |
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |     *x.last_mut().unwrap() = 2;
+   |     +
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize`
+  --> $DIR/assign-non-lval-mut-ref.rs:7:5
+   |
+LL |     x.last_mut().unwrap() += 1;
+   |     ---------------------^^^^^
+   |     |
+   |     cannot use `+=` on type `&mut usize`
+   |
+help: `+=` can be used on `usize`, you can dereference `x.last_mut().unwrap()`
+   |
+LL |     *x.last_mut().unwrap() += 1;
+   |     +
+
+error[E0308]: mismatched types
+  --> $DIR/assign-non-lval-mut-ref.rs:11:9
+   |
+LL |     let y = x.last_mut().unwrap();
+   |             --------------------- expected due to this value
+LL |     y = 2;
+   |         ^ expected `&mut usize`, found integer
+   |
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |     *y = 2;
+   |     +
+
+error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize`
+  --> $DIR/assign-non-lval-mut-ref.rs:13:5
+   |
+LL |     y += 1;
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `&mut usize`
+   |
+help: `+=` can be used on `usize`, you can dereference `y`
+   |
+LL |     *y += 1;
+   |     +
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0070, E0308, E0368.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/typeck/issue-93486.stderr b/src/test/ui/typeck/issue-93486.stderr
index 70b5b63f1cb..167edc8942a 100644
--- a/src/test/ui/typeck/issue-93486.stderr
+++ b/src/test/ui/typeck/issue-93486.stderr
@@ -5,6 +5,11 @@ LL |         vec![].last_mut().unwrap() = 3_u8;
    |         -------------------------- ^
    |         |
    |         cannot assign to this expression
+   |
+help: consider dereferencing here to assign to the mutably borrowed value
+   |
+LL |         *vec![].last_mut().unwrap() = 3_u8;
+   |         +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wasm/wasm-import-module.rs b/src/test/ui/wasm/wasm-import-module.rs
index 4152a1065ca..bff08847d37 100644
--- a/src/test/ui/wasm/wasm-import-module.rs
+++ b/src/test/ui/wasm/wasm-import-module.rs
@@ -1,3 +1,5 @@
+#![feature(link_cfg)]
+
 #[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form
 extern "C" {}
 
@@ -7,4 +9,13 @@ extern "C" {}
 #[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form
 extern "C" {}
 
+#[link(wasm_import_module = "foo", name = "bar")] //~ ERROR: `wasm_import_module` is incompatible with other arguments
+extern "C" {}
+
+#[link(wasm_import_module = "foo", kind = "dylib")] //~ ERROR: `wasm_import_module` is incompatible with other arguments
+extern "C" {}
+
+#[link(wasm_import_module = "foo", cfg(FALSE))] //~ ERROR: `wasm_import_module` is incompatible with other arguments
+extern "C" {}
+
 fn main() {}
diff --git a/src/test/ui/wasm/wasm-import-module.stderr b/src/test/ui/wasm/wasm-import-module.stderr
index 47d6cb68997..e792c33e91a 100644
--- a/src/test/ui/wasm/wasm-import-module.stderr
+++ b/src/test/ui/wasm/wasm-import-module.stderr
@@ -1,20 +1,38 @@
-error: must be of the form `#[link(wasm_import_module = "...")]`
-  --> $DIR/wasm-import-module.rs:1:22
+error: wasm import module must be of the form `wasm_import_module = "string"`
+  --> $DIR/wasm-import-module.rs:3:22
    |
 LL | #[link(name = "...", wasm_import_module)]
    |                      ^^^^^^^^^^^^^^^^^^
 
-error: must be of the form `#[link(wasm_import_module = "...")]`
-  --> $DIR/wasm-import-module.rs:4:22
+error: wasm import module must be of the form `wasm_import_module = "string"`
+  --> $DIR/wasm-import-module.rs:6:22
    |
 LL | #[link(name = "...", wasm_import_module(x))]
    |                      ^^^^^^^^^^^^^^^^^^^^^
 
-error: must be of the form `#[link(wasm_import_module = "...")]`
-  --> $DIR/wasm-import-module.rs:7:22
+error: wasm import module must be of the form `wasm_import_module = "string"`
+  --> $DIR/wasm-import-module.rs:9:22
    |
 LL | #[link(name = "...", wasm_import_module())]
    |                      ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+  --> $DIR/wasm-import-module.rs:12:8
+   |
+LL | #[link(wasm_import_module = "foo", name = "bar")]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+  --> $DIR/wasm-import-module.rs:15:8
+   |
+LL | #[link(wasm_import_module = "foo", kind = "dylib")]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+  --> $DIR/wasm-import-module.rs:18:8
+   |
+LL | #[link(wasm_import_module = "foo", cfg(FALSE))]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 3f052d8eed98c6a24f8b332fb2e6e6249d12d8c
+Subproject a4c1cd0eb6b18082a7e693f5a665548fe1534be
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
index cc354b50afa..826eb0ae6b1 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
@@ -5,7 +5,7 @@ use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_s
 use if_chain::if_chain;
 use rustc_errors::MultiSpan;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, Expr, Guard, HirId, Pat, PatKind};
+use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
@@ -109,7 +109,7 @@ fn check_arm<'tcx>(
             (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
         };
         // the binding must not be used in the if guard
-        if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !is_local_used(cx, *e, binding_id));
+        if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(Let { init: e, .. }))| !is_local_used(cx, *e, binding_id));
         // ...or anywhere in the inner expression
         if match inner {
             IfLetOrMatch::IfLet(_, _, body, els) => {
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 1ae2e20c1e0..d3d3ed2c235 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -11,7 +11,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{
     hir_id::HirIdSet,
     intravisit::{walk_expr, Visitor},
-    Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp,
+    Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -478,7 +478,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                     let mut is_map_used = self.is_map_used;
                     for arm in arms {
                         self.visit_pat(arm.pat);
-                        if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard {
+                        if let Some(Guard::If(guard) | Guard::IfLet(&Let { init: guard, .. })) = arm.guard {
                             self.visit_non_tail_expr(guard);
                         }
                         is_map_used |= self.visit_cond_arm(arm.body);
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 1b19868e4c7..530d6d4de35 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
             if check_inputs(cx, body.params, args);
             let method_def_id = cx.typeck_results().type_dependent_def_id(body.value.hir_id).unwrap();
             let substs = cx.typeck_results().node_substs(body.value.hir_id);
-            let call_ty = cx.tcx.type_of(method_def_id).subst(cx.tcx, substs);
+            let call_ty = cx.tcx.bound_type_of(method_def_id).subst(cx.tcx, substs);
             if check_sig(cx, closure_ty, call_ty);
             then {
                 span_lint_and_then(cx, REDUNDANT_CLOSURE_FOR_METHOD_CALLS, expr.span, "redundant closure", |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 43911a313d5..5c46d6c7df7 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -5,7 +5,7 @@ use rustc_hir::{Body, FnDecl, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{Opaque, PredicateKind::Trait};
+use rustc_middle::ty::{EarlyBinder, Opaque, PredicateKind::Trait};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
@@ -67,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
             let preds = cx.tcx.explicit_item_bounds(id);
             let mut is_future = false;
             for &(p, _span) in preds {
-                let p = p.subst(cx.tcx, subst);
+                let p = EarlyBinder(p).subst(cx.tcx, subst);
                 if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
                     if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 5c3e505c06c..9d8f8999ce4 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
             ExprKind::MethodCall(path, arguments, _) => {
                 let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.typeck_results().node_substs(e.hir_id);
-                let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
+                let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs);
                 check_arguments(cx, arguments, method_type, path.ident.as_str(), "method");
             },
             _ => (),
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index beb812793f8..d66698f8adc 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -596,7 +596,7 @@ impl<'tcx> SideEffectVisit<'tcx> {
                 let mut vars = std::mem::take(&mut self.ret_vars);
                 let _ = arm.guard.as_ref().map(|guard| {
                     self.visit_expr(match guard {
-                        Guard::If(expr) | Guard::IfLet(_, expr) => expr,
+                        Guard::If(expr) | Guard::IfLet(Let { init: expr, .. }) => expr,
                     });
                     vars.append(&mut self.ret_vars);
                 });
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 1507c75ff61..37aac8b2a49 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
             }
 
             // Give up on loops
-            if terminator.successors().any(|s| *s == bb) {
+            if terminator.successors().any(|s| s == bb) {
                 continue;
             }
 
@@ -440,7 +440,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
             // Short-circuit
             if (usage.cloned_used && usage.clone_consumed_or_mutated) ||
                 // Give up on loops
-                tdata.terminator().successors().any(|s| *s == bb)
+                tdata.terminator().successors().any(|s| s == bb)
             {
                 return CloneUsage {
                     cloned_used: true,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index f5e21267a89..be6277332db 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -307,7 +307,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
                     .non_enum_variant()
                     .fields
                     .iter()
-                    .map(|f| cx.tcx.type_of(f.did).subst(cx.tcx, substs));
+                    .map(|f| cx.tcx.bound_type_of(f.did).subst(cx.tcx, substs));
                 let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
                     return ReducedTy::TypeErasure;
                 };
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index ff5be825b78..3f4d0fd199d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -315,11 +315,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 out!("if let Some(Guard::If({expr})) = {arm}.guard;");
                 self.expr(expr);
             },
-            Some(hir::Guard::IfLet(pat, expr)) => {
-                bind!(self, pat, expr);
-                out!("if let Some(Guard::IfLet({pat}, {expr}) = {arm}.guard;");
-                self.pat(pat);
-                self.expr(expr);
+            Some(hir::Guard::IfLet(let_expr)) => {
+                bind!(self, let_expr);
+                out!("if let Some(Guard::IfLet({let_expr}) = {arm}.guard;");
+                self.pat(field!(let_expr.pat));
+                self.expr(field!(let_expr.init));
             },
         }
         self.expr(field!(arm.body));
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index fdb822c3e5b..a80c7ee4929 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -9,7 +9,7 @@ use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind,
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
 use std::cmp::Ordering::{self, Equal};
@@ -420,7 +420,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                 let substs = if self.substs.is_empty() {
                     substs
                 } else {
-                    substs.subst(self.lcx.tcx, self.substs)
+                    EarlyBinder(substs).subst(self.lcx.tcx, self.substs)
                 };
 
                 let result = self
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index f4da625f1e3..aa21f15ee5d 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -301,7 +301,9 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
         match (left, right) {
             (Guard::If(l), Guard::If(r)) => self.eq_expr(l, r),
-            (Guard::IfLet(lp, le), Guard::IfLet(rp, re)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
+            (Guard::IfLet(l), Guard::IfLet(r)) => {
+                self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
+            },
             _ => false,
         }
     }
@@ -894,7 +896,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     pub fn hash_guard(&mut self, g: &Guard<'_>) {
         match g {
-            Guard::If(expr) | Guard::IfLet(_, expr) => {
+            Guard::If(expr) | Guard::IfLet(Let { init: expr, .. }) => {
                 self.hash_expr(expr);
             },
         }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 98a073d122e..6db7f247a99 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -74,11 +74,10 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 use rustc_hir::{
     def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl,
-    ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource,
+    HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource,
     Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
     TraitRef, TyKind, UnOp,
 };
@@ -2068,35 +2067,6 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
     false
 }
 
-struct TestItemNamesVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    names: Vec<Symbol>,
-}
-
-impl<'hir> ItemLikeVisitor<'hir> for TestItemNamesVisitor<'hir> {
-    fn visit_item(&mut self, item: &Item<'_>) {
-        if let ItemKind::Const(ty, _body) = item.kind {
-            if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
-                // We could also check for the type name `test::TestDescAndFn`
-                if let Res::Def(DefKind::Struct, _) = path.res {
-                    let has_test_marker = self
-                        .tcx
-                        .hir()
-                        .attrs(item.hir_id())
-                        .iter()
-                        .any(|a| a.has_name(sym::rustc_test_marker));
-                    if has_test_marker {
-                        self.names.push(item.ident.name);
-                    }
-                }
-            }
-        }
-    }
-    fn visit_trait_item(&mut self, _: &TraitItem<'_>) {}
-    fn visit_impl_item(&mut self, _: &ImplItem<'_>) {}
-    fn visit_foreign_item(&mut self, _: &ForeignItem<'_>) {}
-}
-
 static TEST_ITEM_NAMES_CACHE: SyncOnceCell<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = SyncOnceCell::new();
 
 fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
@@ -2105,10 +2075,28 @@ fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn(
     match map.entry(module) {
         Entry::Occupied(entry) => f(entry.get()),
         Entry::Vacant(entry) => {
-            let mut visitor = TestItemNamesVisitor { tcx, names: Vec::new() };
-            tcx.hir().visit_item_likes_in_module(module, &mut visitor);
-            visitor.names.sort_unstable();
-            f(&*entry.insert(visitor.names))
+            let mut names = Vec::new();
+            for id in tcx.hir().module_items(module) {
+                if matches!(tcx.def_kind(id.def_id), DefKind::Const)
+                    && let item = tcx.hir().item(id)
+                    && let ItemKind::Const(ty, _body) = item.kind {
+                    if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
+                        // We could also check for the type name `test::TestDescAndFn`
+                        if let Res::Def(DefKind::Struct, _) = path.res {
+                            let has_test_marker = tcx
+                                .hir()
+                                .attrs(item.hir_id())
+                                .iter()
+                                .any(|a| a.has_name(sym::rustc_test_marker));
+                            if has_test_marker {
+                                names.push(item.ident.name);
+                            }
+                        }
+                    }
+                }
+            }
+            names.sort_unstable();
+            f(&*entry.insert(names))
         },
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 75808b1b174..66d373a1bf8 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -14,7 +14,6 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
 use rustc_semver::RustcVersion;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_target::spec::abi::Abi::RustIntrinsic;
 use std::borrow::Cow;
 
 type McfResult = Result<(), (Span, Cow<'static, str>)>;
@@ -323,7 +322,7 @@ fn check_terminator<'a, 'tcx>(
                 // within const fns. `transmute` is allowed in all other const contexts.
                 // This won't really scale to more intrinsics or functions. Let's allow const
                 // transmutes in const fn before we add more hacks to this.
-                if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic && tcx.item_name(fn_def_id) == sym::transmute {
+                if tcx.is_intrinsic(fn_def_id) && tcx.item_name(fn_def_id) == sym::transmute {
                     return Err((
                         span,
                         "can only call `transmute` from const items, not `const fn`".into(),
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 7f14a306d0e..b09eb8c6cd1 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -520,7 +520,7 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
         let ty = cx.typeck_results().expr_ty_adjusted(expr).peel_refs();
         match *ty.kind() {
             ty::Closure(_, subs) => Some(ExprFnSig::Closure(subs.as_closure().sig())),
-            ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).subst(cx.tcx, subs))),
+            ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs))),
             ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig)),
             ty::Dynamic(bounds, _) => {
                 let lang_items = cx.tcx.lang_items();
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 3b8b6aa8b689971d3b8776cefe3d809501e1b8f
+Subproject 19ef76477c0ea1722f91ab6b1c2dcb365f06499
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index d75884567af..8532410a1bf 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -138,7 +138,7 @@ async function main(argv) {
     try {
         // This is more convenient that setting fields one by one.
         let args = [
-            "--variable", "DOC_PATH", opts["doc_folder"],
+            "--variable", "DOC_PATH", opts["doc_folder"], "--enable-fail-on-js-error",
         ];
         if (opts["debug"]) {
             debug = true;
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 98d0f5dc656..df3185758bf 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -1,182 +1,6 @@
 const fs = require('fs');
 const path = require('path');
 
-function getNextStep(content, pos, stop) {
-    while (pos < content.length && content[pos] !== stop &&
-           (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) {
-        pos += 1;
-    }
-    if (pos >= content.length) {
-        return null;
-    }
-    if (content[pos] !== stop) {
-        return pos * -1;
-    }
-    return pos;
-}
-
-// Stupid function extractor based on indent. Doesn't support block
-// comments. If someone puts a ' or an " in a block comment this
-// will blow up. Template strings are not tested and might also be
-// broken.
-function extractFunction(content, functionName) {
-    var level = 0;
-    var splitter = "function " + functionName + "(";
-    var stop;
-    var pos, start;
-
-    while (true) {
-        start = content.indexOf(splitter);
-        if (start === -1) {
-            break;
-        }
-        pos = start;
-        while (pos < content.length && content[pos] !== ')') {
-            pos += 1;
-        }
-        if (pos >= content.length) {
-            break;
-        }
-        pos = getNextStep(content, pos + 1, '{');
-        if (pos === null) {
-            break;
-        } else if (pos < 0) {
-            content = content.slice(-pos);
-            continue;
-        }
-        while (pos < content.length) {
-            // Eat single-line comments
-            if (content[pos] === '/' && pos > 0 && content[pos - 1] === '/') {
-                do {
-                    pos += 1;
-                } while (pos < content.length && content[pos] !== '\n');
-
-            // Eat multiline comment.
-            } else if (content[pos] === '*' && pos > 0 && content[pos - 1] === '/') {
-                do {
-                    pos += 1;
-                } while (pos < content.length && content[pos] !== '/' && content[pos - 1] !== '*');
-
-            // Eat quoted strings
-            } else if ((content[pos] === '"' || content[pos] === "'" || content[pos] === "`") &&
-                       (pos === 0 || content[pos - 1] !== '/')) {
-                stop = content[pos];
-                do {
-                    if (content[pos] === '\\') {
-                        pos += 1;
-                    }
-                    pos += 1;
-                } while (pos < content.length && content[pos] !== stop);
-
-            // Otherwise, check for block level.
-            } else if (content[pos] === '{') {
-                level += 1;
-            } else if (content[pos] === '}') {
-                level -= 1;
-                if (level === 0) {
-                    return content.slice(start, pos + 1);
-                }
-            }
-            pos += 1;
-        }
-        content = content.slice(start + 1);
-    }
-    return null;
-}
-
-// Stupid function extractor for array.
-function extractArrayVariable(content, arrayName, kind) {
-    if (typeof kind === "undefined") {
-        kind = "let ";
-    }
-    var splitter = kind + arrayName;
-    while (true) {
-        var start = content.indexOf(splitter);
-        if (start === -1) {
-            break;
-        }
-        var pos = getNextStep(content, start, '=');
-        if (pos === null) {
-            break;
-        } else if (pos < 0) {
-            content = content.slice(-pos);
-            continue;
-        }
-        pos = getNextStep(content, pos, '[');
-        if (pos === null) {
-            break;
-        } else if (pos < 0) {
-            content = content.slice(-pos);
-            continue;
-        }
-        while (pos < content.length) {
-            if (content[pos] === '"' || content[pos] === "'") {
-                var stop = content[pos];
-                do {
-                    if (content[pos] === '\\') {
-                        pos += 2;
-                    } else {
-                        pos += 1;
-                    }
-                } while (pos < content.length &&
-                         (content[pos] !== stop || content[pos - 1] === '\\'));
-            } else if (content[pos] === ']' &&
-                       pos + 1 < content.length &&
-                       content[pos + 1] === ';') {
-                return content.slice(start, pos + 2);
-            }
-            pos += 1;
-        }
-        content = content.slice(start + 1);
-    }
-    if (kind === "let ") {
-        return extractArrayVariable(content, arrayName, "const ");
-    }
-    return null;
-}
-
-// Stupid function extractor for variable.
-function extractVariable(content, varName, kind) {
-    if (typeof kind === "undefined") {
-        kind = "let ";
-    }
-    var splitter = kind + varName;
-    while (true) {
-        var start = content.indexOf(splitter);
-        if (start === -1) {
-            break;
-        }
-        var pos = getNextStep(content, start, '=');
-        if (pos === null) {
-            break;
-        } else if (pos < 0) {
-            content = content.slice(-pos);
-            continue;
-        }
-        while (pos < content.length) {
-            if (content[pos] === '"' || content[pos] === "'") {
-                var stop = content[pos];
-                do {
-                    if (content[pos] === '\\') {
-                        pos += 2;
-                    } else {
-                        pos += 1;
-                    }
-                } while (pos < content.length &&
-                         (content[pos] !== stop || content[pos - 1] === '\\'));
-            } else if (content[pos] === ';' || content[pos] === ',') {
-                return content.slice(start, pos + 1);
-            }
-            pos += 1;
-        }
-        content = content.slice(start + 1);
-    }
-    if (kind === "let ") {
-        return extractVariable(content, varName, "const ");
-    }
-    return null;
-}
-
 function loadContent(content) {
     var Module = module.constructor;
     var m = new Module();
@@ -194,20 +18,6 @@ function readFile(filePath) {
     return fs.readFileSync(filePath, 'utf8');
 }
 
-function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) {
-    var content = '';
-    for (var i = 0; i < thingsToLoad.length; ++i) {
-        var tmp = funcToCall(fileContent, thingsToLoad[i]);
-        if (tmp === null) {
-            console.log('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"');
-            process.exit(1);
-        }
-        content += tmp;
-        content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';';
-    }
-    return content;
-}
-
 function contentToDiffLine(key, value) {
     return `"${key}": "${value}",`;
 }
@@ -264,46 +74,6 @@ function lookForEntry(entry, data) {
     return null;
 }
 
-function loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate) {
-    if (searchIndex[searchIndex.length - 1].length === 0) {
-        searchIndex.pop();
-    }
-    searchIndex.pop();
-    var fullSearchIndex = searchIndex.join("\n") + '\nexports.rawSearchIndex = searchIndex;';
-    searchIndex = loadContent(fullSearchIndex);
-    var finalJS = "";
-
-    var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER",
-                           "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
-                           "TY_PRIMITIVE", "TY_KEYWORD",
-                           "levenshtein_row2"];
-    // execQuery first parameter is built in getQuery (which takes in the search input).
-    // execQuery last parameter is built in buildIndex.
-    // buildIndex requires the hashmap from search-index.
-    var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
-                           "buildIndex", "execQuery", "parseQuery", "createQueryResults",
-                           "isWhitespace", "isSpecialStartCharacter", "isStopCharacter",
-                           "parseInput", "getItemsBefore", "getNextElem", "createQueryElement",
-                           "isReturnArrow", "isPathStart", "getStringElem", "newParsedQuery",
-                           "itemTypeFromName", "isEndCharacter", "isErrorCharacter",
-                           "isIdentCharacter", "isSeparatorCharacter", "getIdentEndPosition",
-                           "checkExtraTypeFilterCharacters", "isWhitespaceCharacter"];
-
-    const functions = ["hasOwnPropertyRustdoc", "onEach"];
-    ALIASES = {};
-    finalJS += 'window = { "currentCrate": "' + crate + '", rootPath: "../" };\n';
-    finalJS += loadThings(functions, 'function', extractFunction, storageJs);
-    finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, searchJs);
-    finalJS += loadThings(variablesToLoad, 'variable', extractVariable, searchJs);
-    finalJS += loadThings(functionsToLoad, 'function', extractFunction, searchJs);
-
-    var loaded = loadContent(finalJS);
-    var index = loaded.buildIndex(searchIndex.rawSearchIndex);
-
-    return [loaded, index];
-}
-
 // This function checks if `expected` has all the required fields needed for the checks.
 function checkNeededFields(fullPath, expected, error_text, queryName, position) {
     let fieldsToCheck;
@@ -359,8 +129,7 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
                 'compared to EXPECTED');
         }
     } else if (expected !== null && typeof expected !== "undefined" &&
-               expected.constructor == Object)
-    {
+               expected.constructor == Object) {
         for (const key in expected) {
             if (!expected.hasOwnProperty(key)) {
                 continue;
@@ -382,21 +151,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
     }
 }
 
-function runParser(query, expected, loaded, loadedFile, queryName) {
+function runParser(query, expected, parseQuery, queryName) {
     var error_text = [];
     checkNeededFields("", expected, error_text, queryName, null);
     if (error_text.length === 0) {
-        valueCheck('', expected, loaded.parseQuery(query), error_text, queryName);
+        valueCheck('', expected, parseQuery(query), error_text, queryName);
     }
     return error_text;
 }
 
-function runSearch(query, expected, index, loaded, loadedFile, queryName) {
-    const filter_crate = loadedFile.FILTER_CRATE;
+function runSearch(query, expected, doSearch, loadedFile, queryName) {
     const ignore_order = loadedFile.ignore_order;
     const exact_check = loadedFile.exact_check;
 
-    var results = loaded.execQuery(loaded.parseQuery(query), index, filter_crate);
+    var results = doSearch(query, loadedFile.FILTER_CRATE);
     var error_text = [];
 
     for (var key in expected) {
@@ -488,7 +256,7 @@ function runCheck(loadedFile, key, callback) {
     return 0;
 }
 
-function runChecks(testFile, loaded, index) {
+function runChecks(testFile, doSearch, parseQuery) {
     var checkExpected = false;
     var checkParsed = false;
     var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;';
@@ -518,24 +286,40 @@ function runChecks(testFile, loaded, index) {
 
     if (checkExpected) {
         res += runCheck(loadedFile, "EXPECTED", (query, expected, text) => {
-            return runSearch(query, expected, index, loaded, loadedFile, text);
+            return runSearch(query, expected, doSearch, loadedFile, text);
         });
     }
     if (checkParsed) {
         res += runCheck(loadedFile, "PARSED", (query, expected, text) => {
-            return runParser(query, expected, loaded, loadedFile, text);
+            return runParser(query, expected, parseQuery, text);
         });
     }
     return res;
 }
 
-function load_files(doc_folder, resource_suffix, crate) {
-    var searchJs = readFile(path.join(doc_folder, "search" + resource_suffix + ".js"));
-    var storageJs = readFile(path.join(doc_folder, "storage" + resource_suffix + ".js"));
-    var searchIndex = readFile(
-        path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n");
-
-    return loadSearchJsAndIndex(searchJs, searchIndex, storageJs, crate);
+/**
+ * Load searchNNN.js and search-indexNNN.js.
+ *
+ * @param {string} doc_folder      - Path to a folder generated by running rustdoc
+ * @param {string} resource_suffix - Version number between filename and .js, e.g. "1.59.0"
+ * @returns {Object}               - Object containing two keys: `doSearch`, which runs a search
+ *   with the loaded index and returns a table of results; and `parseQuery`, which is the
+ *   `parseQuery` function exported from the search module.
+ */
+function loadSearchJS(doc_folder, resource_suffix) {
+    const searchJs = path.join(doc_folder, "search" + resource_suffix + ".js");
+    const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js");
+    const searchIndex = require(searchIndexJs);
+    const searchModule = require(searchJs);
+    const searchWords = searchModule.initSearch(searchIndex.searchIndex);
+
+    return {
+        doSearch: function (queryStr, filterCrate, currentCrate) {
+            return searchModule.execQuery(searchModule.parseQuery(queryStr), searchWords,
+                filterCrate, currentCrate);
+        },
+        parseQuery: searchModule.parseQuery,
+    }
 }
 
 function showHelp() {
@@ -598,35 +382,34 @@ function parseOptions(args) {
     return null;
 }
 
-function checkFile(test_file, opts, loaded, index) {
-    const test_name = path.basename(test_file, ".js");
-
-    process.stdout.write('Checking "' + test_name + '" ... ');
-    return runChecks(test_file, loaded, index);
-}
-
 function main(argv) {
     var opts = parseOptions(argv.slice(2));
     if (opts === null) {
         return 1;
     }
 
-    var [loaded, index] = load_files(
+    let parseAndSearch = loadSearchJS(
         opts["doc_folder"],
-        opts["resource_suffix"],
-        opts["crate_name"]);
+        opts["resource_suffix"]);
     var errors = 0;
 
+    let doSearch = function (queryStr, filterCrate) {
+        return parseAndSearch.doSearch(queryStr, filterCrate, opts["crate_name"]);
+    };
+
     if (opts["test_file"].length !== 0) {
-        opts["test_file"].forEach(function(file) {
-            errors += checkFile(file, opts, loaded, index);
+        opts["test_file"].forEach(function (file) {
+            process.stdout.write(`Testing ${file} ... `);
+            errors += runChecks(file, doSearch, parseAndSearch.parseQuery);
         });
     } else if (opts["test_folder"].length !== 0) {
-        fs.readdirSync(opts["test_folder"]).forEach(function(file) {
+        fs.readdirSync(opts["test_folder"]).forEach(function (file) {
             if (!file.endsWith(".js")) {
                 return;
             }
-            errors += checkFile(path.join(opts["test_folder"], file), opts, loaded, index);
+            process.stdout.write(`Testing ${file} ... `);
+            errors += runChecks(path.join(opts["test_folder"], file), doSearch,
+                    parseAndSearch.parseQuery);
         });
     }
     return errors > 0 ? 1 : 0;
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 26c429eb94f..f4b2bcf2815 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -226,7 +226,7 @@ fn rewrite_macro_inner(
     }
     // Format well-known macros which cannot be parsed as a valid AST.
     if macro_name == "lazy_static!" && !has_comment {
-        if let success @ Some(..) = format_lazy_static(context, shape, ts.trees().collect()) {
+        if let success @ Some(..) = format_lazy_static(context, shape, ts.clone()) {
             return success;
         }
     }
@@ -855,7 +855,7 @@ impl MacroArgParser {
 
     /// Returns a collection of parsed macro def's arguments.
     fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
-        let mut iter = tokens.trees();
+        let mut iter = tokens.into_trees();
 
         while let Some(tok) = iter.next() {
             match tok {
diff --git a/src/version b/src/version
index 76d05362056..af92bdd9f58 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.62.0
+1.63.0