about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-27 17:10:58 +0000
committerbors <bors@rust-lang.org>2022-11-27 17:10:58 +0000
commit1eb62b1235fd77200e6bd967d70e83c0f2497233 (patch)
treefa4a9e83e0ac95a98069059afcd1b1d3cc56f3a8
parent454784afba5bf35b5ff14ada0e31265ad1d75e73 (diff)
parent55cf566f041e110d5cfe39b49391dcb33f8da37b (diff)
downloadrust-1eb62b1235fd77200e6bd967d70e83c0f2497233.tar.gz
rust-1eb62b1235fd77200e6bd967d70e83c0f2497233.zip
Auto merge of #104983 - matthiaskrgr:rollup-018sk73, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #95836 (Use `rust_out{exe_suffix}` for doctests)
 - #104882 (notify lcnr on changes to `ObligationCtxt`)
 - #104892 (Explain how to get the discriminant out of a `#[repr(T)] enum` with payload)
 - #104917 (Allow non-org members to label `requires-debug-assertions`)
 - #104931 (Pretty-print generators with their `generator_kind`)
 - #104934 (Remove redundant `all` in cfg)
 - #104944 (Support unit tests for jsondoclint)
 - #104946 (rustdoc: improve popover focus handling JS)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs25
-rw-r--r--compiler/rustc_span/src/analyze_source_file.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--library/core/src/mem/mod.rs61
-rw-r--r--library/std/src/sys/common/alloc.rs12
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/test.rs36
-rw-r--r--src/librustdoc/doctest.rs16
-rw-r--r--src/librustdoc/html/static/js/main.js20
-rw-r--r--src/librustdoc/html/static/js/settings.js2
-rw-r--r--src/test/run-make/coverage-reports/Makefile2
-rw-r--r--src/test/rustdoc-gui/notable-trait.goml25
-rw-r--r--src/test/rustdoc-gui/pocket-menu.goml21
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml6
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.rs4
-rw-r--r--src/test/ui/async-await/async-block-control-flow-static-semantics.stderr8
-rw-r--r--src/test/ui/async-await/generator-desc.stderr8
-rw-r--r--src/test/ui/async-await/issue-67252-unnamed-future.stderr2
-rw-r--r--src/test/ui/async-await/issue-86507.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr2
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr22
-rw-r--r--src/test/ui/generator/clone-impl-async.rs27
-rw-r--r--src/test/ui/generator/clone-impl-async.stderr48
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.rs2
-rw-r--r--src/test/ui/impl-trait/issue-55872-3.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.stderr2
-rw-r--r--src/test/ui/pattern/non-structural-match-types.stderr2
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr2
-rw-r--r--src/tools/jsondoclint/src/json_find.rs5
-rw-r--r--src/tools/jsondoclint/src/json_find/tests.rs27
-rw-r--r--src/tools/jsondoclint/src/main.rs4
-rw-r--r--triagebot.toml9
37 files changed, 318 insertions, 114 deletions
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 89661918d05..fd01fcf1fc8 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -13,17 +13,17 @@
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
-#[cfg(all(any(target_arch = "x86",
+#[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
               target_arch = "powerpc",
-              target_arch = "powerpc64")))]
+              target_arch = "powerpc64"))]
 const MIN_ALIGN: usize = 8;
-#[cfg(all(any(target_arch = "x86_64",
+#[cfg(any(target_arch = "x86_64",
               target_arch = "aarch64",
               target_arch = "mips64",
               target_arch = "s390x",
-              target_arch = "sparc64")))]
+              target_arch = "sparc64"))]
 const MIN_ALIGN: usize = 16;
 
 pub struct System;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index bfc950eff5c..f4e1f84bfb3 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -376,7 +376,7 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
         ccx: &ConstCx<'_, 'tcx>,
         span: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
+        let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
         if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
             ccx.tcx.sess.create_feature_err(
                 UnallowedOpInConstContext { span, msg },
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 208d2fb42e4..660b402f988 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1526,9 +1526,9 @@ pub enum AsyncGeneratorKind {
 impl fmt::Display for AsyncGeneratorKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match self {
-            AsyncGeneratorKind::Block => "`async` block",
-            AsyncGeneratorKind::Closure => "`async` closure body",
-            AsyncGeneratorKind::Fn => "`async fn` body",
+            AsyncGeneratorKind::Block => "async block",
+            AsyncGeneratorKind::Closure => "async closure body",
+            AsyncGeneratorKind::Fn => "async fn body",
         })
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 50722c42a6c..4e044d39d50 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -118,7 +118,8 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
                 } else {
                     let note = format!(
                         "the type is part of the {} because of this {}",
-                        self.kind, yield_data.source
+                        self.kind.descr(),
+                        yield_data.source
                     );
 
                     self.fcx
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index f93dc15068e..44b85098630 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -681,25 +681,20 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Str => p!("str"),
             ty::Generator(did, substs, movability) => {
-                // FIXME(swatinem): async constructs used to be pretty printed
-                // as `impl Future` previously due to the `from_generator` wrapping.
-                // lets special case this here for now to avoid churn in diagnostics.
-                let generator_kind = self.tcx().generator_kind(did);
-                if matches!(generator_kind, Some(hir::GeneratorKind::Async(..))) {
-                    let return_ty = substs.as_generator().return_ty();
-                    p!(write("impl Future<Output = {}>", return_ty));
-
-                    return Ok(self);
-                }
-
                 p!(write("["));
-                match movability {
-                    hir::Movability::Movable => {}
-                    hir::Movability::Static => p!("static "),
+                let generator_kind = self.tcx().generator_kind(did).unwrap();
+                let should_print_movability =
+                    self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen;
+
+                if should_print_movability {
+                    match movability {
+                        hir::Movability::Movable => {}
+                        hir::Movability::Static => p!("static "),
+                    }
                 }
 
                 if !self.should_print_verbose() {
-                    p!("generator");
+                    p!(write("{}", generator_kind));
                     // FIXME(eddyb) should use `def_span`.
                     if let Some(did) = did.as_local() {
                         let span = self.tcx().def_span(did);
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index 5987fb2a198..47aa4dfba42 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -41,7 +41,7 @@ pub fn analyze_source_file(
 }
 
 cfg_if::cfg_if! {
-    if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64")))] {
+    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
         fn analyze_source_file_dispatch(src: &str,
                                     source_file_start_pos: BytePos,
                                     lines: &mut Vec<BytePos>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index da6ca30cc9a..b7728b054e4 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2673,7 +2673,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 let sp = self.tcx.def_span(def_id);
 
                                 // Special-case this to say "async block" instead of `[static generator]`.
-                                let kind = tcx.generator_kind(def_id).unwrap();
+                                let kind = tcx.generator_kind(def_id).unwrap().descr();
                                 err.span_note(
                                     sp,
                                     &format!("required because it's used within this {}", kind),
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index ec35914f1e3..383bdc7b6e2 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1113,7 +1113,10 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// # Stability
 ///
 /// The discriminant of an enum variant may change if the enum definition changes. A discriminant
-/// of some variant will not change between compilations with the same compiler.
+/// of some variant will not change between compilations with the same compiler. See the [Reference]
+/// for more information.
+///
+/// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
 ///
 /// # Examples
 ///
@@ -1129,6 +1132,62 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2)));
 /// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3)));
 /// ```
+///
+/// ## Accessing the numeric value of the discriminant
+///
+/// Note that it is *undefined behavior* to [`transmute`] from [`Discriminant`] to a primitive!
+///
+/// If an enum has only unit variants, then the numeric value of the discriminant can be accessed
+/// with an [`as`] cast:
+///
+/// ```
+/// enum Enum {
+///     Foo,
+///     Bar,
+///     Baz,
+/// }
+///
+/// assert_eq!(0, Enum::Foo as isize);
+/// assert_eq!(1, Enum::Bar as isize);
+/// assert_eq!(2, Enum::Baz as isize);
+/// ```
+///
+/// If an enum has opted-in to having a [primitive representation] for its discriminant,
+/// then it's possible to use pointers to read the memory location storing the discriminant.
+/// That **cannot** be done for enums using the [default representation], however, as it's
+/// undefined what layout the discriminant has and where it's stored — it might not even be
+/// stored at all!
+///
+/// [`as`]: ../../std/keyword.as.html
+/// [primitive representation]: ../../reference/type-layout.html#primitive-representations
+/// [default representation]: ../../reference/type-layout.html#the-default-representation
+/// ```
+/// #[repr(u8)]
+/// enum Enum {
+///     Unit,
+///     Tuple(bool),
+///     Struct { a: bool },
+/// }
+///
+/// impl Enum {
+///     fn discriminant(&self) -> u8 {
+///         // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union`
+///         // between `repr(C)` structs, each of which has the `u8` discriminant as its first
+///         // field, so we can read the discriminant without offsetting the pointer.
+///         unsafe { *<*const _>::from(self).cast::<u8>() }
+///     }
+/// }
+///
+/// let unit_like = Enum::Unit;
+/// let tuple_like = Enum::Tuple(true);
+/// let struct_like = Enum::Struct { a: false };
+/// assert_eq!(0, unit_like.discriminant());
+/// assert_eq!(1, tuple_like.discriminant());
+/// assert_eq!(2, struct_like.discriminant());
+///
+/// // ⚠️ This is undefined behavior. Don't do this. ⚠️
+/// // assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) });
+/// ```
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")]
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index e8e7c51cb9b..3edbe728077 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -4,7 +4,7 @@ use crate::ptr;
 
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values.
-#[cfg(all(any(
+#[cfg(any(
     target_arch = "x86",
     target_arch = "arm",
     target_arch = "mips",
@@ -16,9 +16,9 @@ use crate::ptr;
     target_arch = "hexagon",
     all(target_arch = "riscv32", not(target_os = "espidf")),
     all(target_arch = "xtensa", not(target_os = "espidf")),
-)))]
+))]
 pub const MIN_ALIGN: usize = 8;
-#[cfg(all(any(
+#[cfg(any(
     target_arch = "x86_64",
     target_arch = "aarch64",
     target_arch = "mips64",
@@ -26,13 +26,13 @@ pub const MIN_ALIGN: usize = 8;
     target_arch = "sparc64",
     target_arch = "riscv64",
     target_arch = "wasm64",
-)))]
+))]
 pub const MIN_ALIGN: usize = 16;
 // The allocator on the esp-idf platform guarantees 4 byte alignment.
-#[cfg(all(any(
+#[cfg(any(
     all(target_arch = "riscv32", target_os = "espidf"),
     all(target_arch = "xtensa", target_os = "espidf"),
-)))]
+))]
 pub const MIN_ALIGN: usize = 4;
 
 pub unsafe fn realloc_fallback(
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 251431a15eb..cff5fd8c5b0 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -644,6 +644,7 @@ impl<'a> Builder<'a> {
                 test::CrateLibrustc,
                 test::CrateRustdoc,
                 test::CrateRustdocJsonTypes,
+                test::CrateJsonDocLint,
                 test::Linkcheck,
                 test::TierCheck,
                 test::ReplacePlaceholderTest,
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index a69979d7f07..39cedfdac5f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -91,6 +91,42 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct CrateJsonDocLint {
+    host: TargetSelection,
+}
+
+impl Step for CrateJsonDocLint {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/jsondoclint")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(CrateJsonDocLint { host: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let bootstrap_host = builder.config.build;
+        let compiler = builder.compiler(0, bootstrap_host);
+
+        let cargo = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolBootstrap,
+            bootstrap_host,
+            "test",
+            "src/tools/jsondoclint",
+            SourceType::InTree,
+            &[],
+        );
+        try_run(builder, &mut cargo.into());
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Linkcheck {
     host: TargetSelection,
 }
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index cb50c3ae829..81d9c46447a 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -19,7 +19,7 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
-use rustc_target::spec::TargetTriple;
+use rustc_target::spec::{Target, TargetTriple};
 use tempfile::Builder as TempFileBuilder;
 
 use std::env;
@@ -293,6 +293,16 @@ struct UnusedExterns {
     unused_extern_names: Vec<String>,
 }
 
+fn add_exe_suffix(input: String, target: &TargetTriple) -> String {
+    let exe_suffix = match target {
+        TargetTriple::TargetTriple(_) => Target::expect_builtin(target).options.exe_suffix,
+        TargetTriple::TargetJson { contents, .. } => {
+            Target::from_json(contents.parse().unwrap()).unwrap().0.options.exe_suffix
+        }
+    };
+    input + &exe_suffix
+}
+
 fn run_test(
     test: &str,
     crate_name: &str,
@@ -313,7 +323,9 @@ fn run_test(
     let (test, line_offset, supports_color) =
         make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
 
-    let output_file = outdir.path().join("rust_out");
+    // Make sure we emit well-formed executable names for our target.
+    let rust_out = add_exe_suffix("rust_out".to_owned(), &target);
+    let output_file = outdir.path().join(rust_out);
 
     let rustc_binary = rustdoc_options
         .test_builder
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 2a109ffbc60..7230df36c07 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -202,6 +202,7 @@ function loadCss(cssUrl) {
         if (event.ctrlKey || event.altKey || event.metaKey) {
             return;
         }
+        window.hideAllModals(false);
         addClass(getSettingsButton(), "rotate");
         event.preventDefault();
         // Sending request for the CSS and the JS files at the same time so it will
@@ -377,7 +378,7 @@ function loadCss(cssUrl) {
         }
         ev.preventDefault();
         searchState.defocus();
-        window.hidePopoverMenus();
+        window.hideAllModals(true); // true = reset focus for notable traits
     }
 
     function handleShortcut(ev) {
@@ -767,6 +768,7 @@ function loadCss(cssUrl) {
     };
 
     function showSidebar() {
+        window.hideAllModals(false);
         window.rustdocMobileScrollLock();
         const sidebar = document.getElementsByClassName("sidebar")[0];
         addClass(sidebar, "shown");
@@ -843,7 +845,7 @@ function loadCss(cssUrl) {
             // Make this function idempotent.
             return;
         }
-        hideNotable(false);
+        window.hideAllModals(false);
         const ty = e.getAttribute("data-ty");
         const wrapper = document.createElement("div");
         wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>";
@@ -1050,13 +1052,23 @@ function loadCss(cssUrl) {
     }
 
     /**
+     * Hide popover menus, notable trait tooltips, and the sidebar (if applicable).
+     *
+     * Pass "true" to reset focus for notable traits.
+     */
+    window.hideAllModals = function(switchFocus) {
+        hideSidebar();
+        window.hidePopoverMenus();
+        hideNotable(switchFocus);
+    };
+
+    /**
      * Hide all the popover menus.
      */
     window.hidePopoverMenus = function() {
         onEachLazy(document.querySelectorAll(".search-form .popover"), elem => {
             elem.style.display = "none";
         });
-        hideNotable(false);
     };
 
     /**
@@ -1081,7 +1093,7 @@ function loadCss(cssUrl) {
     function showHelp() {
         const menu = getHelpMenu(true);
         if (menu.style.display === "none") {
-            window.hidePopoverMenus();
+            window.hideAllModals();
             menu.style.display = "";
         }
     }
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 5256ae916a7..589bfc79360 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -268,7 +268,7 @@
             event.preventDefault();
             const shouldDisplaySettings = settingsMenu.style.display === "none";
 
-            window.hidePopoverMenus();
+            window.hideAllModals();
             if (shouldDisplaySettings) {
                 displaySettings();
             }
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
index 407992c9f43..436aebf1174 100644
--- a/src/test/run-make/coverage-reports/Makefile
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -132,7 +132,7 @@ include clear_expected_if_blessed
 			--instr-profile="$(TMPDIR)"/$@.profdata \
 			$(call BIN,"$(TMPDIR)"/$@) \
 			$$( \
-				for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \
+				for file in $(TMPDIR)/rustdoc-$@/*/rust_out*; do \
 				[ -x "$$file" ] && printf "%s %s " -object $$file; \
 				done \
 			) \
diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml
index aab3b11433e..7e24af47ee8 100644
--- a/src/test/rustdoc-gui/notable-trait.goml
+++ b/src/test/rustdoc-gui/notable-trait.goml
@@ -200,12 +200,14 @@ move-cursor-to: "//*[@class='notable popover']"
 assert-count: ("//*[@class='notable popover']", 1)
 press-key: "Escape"
 assert-count: ("//*[@class='notable popover']", 0)
+assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
 
 // Check that clicking outside works.
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
 assert-count: ("//*[@class='notable popover']", 1)
 click: ".search-input"
 assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
 
 // Check that pressing tab over and over works.
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
@@ -249,3 +251,26 @@ click: "#settings-menu a"
 press-key: "Escape"
 // We ensure we didn't come back to the previous focused item.
 assert-window-property-false: {"scrollY": |scroll|}
+
+// Opening the mobile sidebar should close the popover.
+size: (650, 600)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
+// Clicking a notable popover should close the sidebar.
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+assert-false: "//*[@class='sidebar shown']"
+
+// Also check the focus handling for the help button.
+size: (1100, 600)
+reload:
+assert-count: ("//*[@class='notable popover']", 0)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable popover']", 1)
+click: "#help-button a"
+assert-count: ("//*[@class='notable popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
index fb63ea62a48..c3649dc7bda 100644
--- a/src/test/rustdoc-gui/pocket-menu.goml
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -75,3 +75,24 @@ assert-css: (
 )
 compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Opening the mobile sidebar should close the settings popover.
+size: (650, 600)
+click: "#settings-menu a"
+assert-css: ("#settings-menu .popover", {"display": "block"})
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-css: ("#settings-menu .popover", {"display": "none"})
+// Opening the settings popover should close the sidebar.
+click: "#settings-menu a"
+assert-css: ("#settings-menu .popover", {"display": "block"})
+assert-false: "//*[@class='sidebar shown']"
+
+// Opening the settings popover at start (which async loads stuff) should also close.
+reload:
+click: ".sidebar-menu-toggle"
+assert: "//*[@class='sidebar shown']"
+assert-false: "#settings-menu .popover"
+click: "#settings-menu a"
+assert-false: "//*[@class='sidebar shown']"
+wait-for: "#settings-menu .popover"
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index 453873f1b81..840091799a7 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -32,6 +32,12 @@ assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In test_docs']/pa
 click: "body"
 assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
+// Open the sidebar menu, and make sure pressing Escape closes it.
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"left": "0px"})
+press-key: "Escape"
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
+
 // Check that the topbar is visible
 assert-property: (".mobile-topbar", {"clientHeight": "45"})
 
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
index 446212ca767..bc9d127931d 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs
@@ -15,7 +15,7 @@ fn return_targets_async_block_not_fn() -> u8 {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+    //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
 }
 
 async fn return_targets_async_block_not_async_fn() -> u8 {
@@ -24,7 +24,7 @@ async fn return_targets_async_block_not_async_fn() -> u8 {
         return 0u8;
     };
     let _: &dyn Future<Output = ()> = &block;
-    //~^ ERROR expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+    //~^ ERROR to be a future that resolves to `()`, but it resolves to `u8`
 }
 
 fn no_break_in_async_block() {
diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
index b8ca64fae83..c4487eb840a 100644
--- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -29,13 +29,13 @@ LL | |
 LL | | }
    | |_^ expected `u8`, found `()`
 
-error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:26:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:12:43
@@ -45,13 +45,13 @@ LL | fn return_targets_async_block_not_fn() -> u8 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0271]: expected `impl Future<Output = u8>` to be a future that resolves to `()`, but it resolves to `u8`
+error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to be a future that resolves to `()`, but it resolves to `u8`
   --> $DIR/async-block-control-flow-static-semantics.rs:17:39
    |
 LL |     let _: &dyn Future<Output = ()> = &block;
    |                                       ^^^^^^ expected `()`, found `u8`
    |
-   = note: required for the cast from `impl Future<Output = u8>` to the object type `dyn Future<Output = ()>`
+   = note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
 
 error[E0308]: mismatched types
   --> $DIR/async-block-control-flow-static-semantics.rs:49:44
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index 774c97966b1..1686153acf9 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -8,8 +8,8 @@ LL |     fun(async {}, async {});
    |         |         arguments to this function are incorrect
    |         the expected `async` block
    |
-   = note: expected `async` block `impl Future<Output = ()>` (`async` block)
-              found `async` block `impl Future<Output = ()>` (`async` block)
+   = note: expected `async` block `[async block@$DIR/generator-desc.rs:10:9: 10:17]`
+              found `async` block `[async block@$DIR/generator-desc.rs:10:19: 10:27]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
@@ -53,8 +53,8 @@ LL |     fun((async || {})(), (async || {})());
    |     |             the expected `async` closure body
    |     arguments to this function are incorrect
    |
-   = note: expected `async` closure body `impl Future<Output = ()>` (`async` closure body)
-              found `async` closure body `impl Future<Output = ()>` (`async` closure body)
+   = note: expected `async` closure body `[async closure body@$DIR/generator-desc.rs:14:19: 14:21]`
+              found `async` closure body `[async closure body@$DIR/generator-desc.rs:14:36: 14:38]`
 note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
index af99b608ca1..fcba4410ba9 100644
--- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr
+++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
@@ -8,7 +8,7 @@ LL | |         AFuture.await;
 LL | |     });
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*mut ()`
+   = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:18:11: 21:6]`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-67252-unnamed-future.rs:20:16
    |
diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr
index 0e21dba980d..8c2c06da25c 100644
--- a/src/test/ui/async-await/issue-86507.stderr
+++ b/src/test/ui/async-await/issue-86507.stderr
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
    |
 LL |                     let x = x;
    |                             ^ has type `&T` which is not `Send`, because `T` is not `Sync`
-   = note: required for the cast from `impl Future<Output = ()>` to the object type `dyn Future<Output = ()> + Send`
+   = note: required for the cast from `[async block@$DIR/issue-86507.rs:18:17: 20:18]` to the object type `dyn Future<Output = ()> + Send`
 help: consider further restricting this bound
    |
 LL |     fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
index a723503776b..ab196dca20c 100644
--- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
@@ -8,7 +8,7 @@ LL | |         bar(Foo(std::ptr::null())).await;
 LL | |     })
    | |_____^ future created by async block is not `Send`
    |
-   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8`
+   = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:16:17: 19:6]`, the trait `Send` is not implemented for `*const u8`
 note: future is not `Send` as this value is used across an await
   --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
    |
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index 6f22d2c593a..4804df13340 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -1,4 +1,4 @@
-error[E0277]: `impl Future<Output = u32>` is not a future
+error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
@@ -7,18 +7,18 @@ LL | |     x
 LL | | }
    | | ^
    | | |
-   | |_`impl Future<Output = u32>` is not a future
+   | |_`[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
    |   required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
-   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
+   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
    |                                      ^^^^^^^^^^^^^^^^^^ required by this bound in `identity_future`
 
-error[E0277]: the size for values of type `<impl Future<Output = u32> as Future>::Output` cannot be known at compilation time
+error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
   --> $DIR/async.rs:7:29
    |
 LL |   async fn foo(x: u32) -> u32 {
@@ -27,23 +27,23 @@ LL | |     x
 LL | | }
    | |_^ doesn't have a size known at compile-time
    |
-   = help: the trait `Sized` is not implemented for `<impl Future<Output = u32> as Future>::Output`
+   = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
 note: required by a bound in `identity_future`
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
 LL | pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut {
    |                              ^ required by this bound in `identity_future`
 
-error[E0277]: `impl Future<Output = u32>` is not a future
+error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
   --> $DIR/async.rs:7:25
    |
 LL | async fn foo(x: u32) -> u32 {
-   |                         ^^^ `impl Future<Output = u32>` is not a future
+   |                         ^^^ `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
    |
-   = help: the trait `Future` is not implemented for `impl Future<Output = u32>`
-   = note: impl Future<Output = u32> must be a future or must implement `IntoFuture` to be awaited
+   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
+   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
 
-error[E0280]: the requirement `<impl Future<Output = u32> as Future>::Output == u32` is not satisfied
+error[E0280]: the requirement `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output == u32` is not satisfied
   --> $DIR/async.rs:7:25
    |
 LL | async fn foo(x: u32) -> u32 {
diff --git a/src/test/ui/generator/clone-impl-async.rs b/src/test/ui/generator/clone-impl-async.rs
index 83c51526b7b..9e9b59d3633 100644
--- a/src/test/ui/generator/clone-impl-async.rs
+++ b/src/test/ui/generator/clone-impl-async.rs
@@ -15,42 +15,42 @@ fn main() {
         drop(non_clone);
     };
     check_copy(&inner_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&inner_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let non_clone = NonClone;
     let outer_non_clone = async move {
         drop(non_clone);
     };
     check_copy(&outer_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&outer_non_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let maybe_copy_clone = async move {};
     check_copy(&maybe_copy_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&maybe_copy_clone);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let inner_non_clone_fn = the_inner_non_clone_fn();
     check_copy(&inner_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&inner_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let outer_non_clone_fn = the_outer_non_clone_fn(NonClone);
     check_copy(&outer_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&outer_non_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 
     let maybe_copy_clone_fn = the_maybe_copy_clone_fn();
     check_copy(&maybe_copy_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+    //~^ ERROR : Copy` is not satisfied
     check_clone(&maybe_copy_clone_fn);
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+    //~^ ERROR : Clone` is not satisfied
 }
 
 async fn the_inner_non_clone_fn() {
@@ -64,8 +64,7 @@ async fn the_outer_non_clone_fn(non_clone: NonClone) {
     drop(non_clone);
 }
 
-async fn the_maybe_copy_clone_fn() {
-}
+async fn the_maybe_copy_clone_fn() {}
 
 fn check_copy<T: Copy>(_x: &T) {}
 fn check_clone<T: Clone>(_x: &T) {}
diff --git a/src/test/ui/generator/clone-impl-async.stderr b/src/test/ui/generator/clone-impl-async.stderr
index cbb58d2af18..9854728876f 100644
--- a/src/test/ui/generator/clone-impl-async.stderr
+++ b/src/test/ui/generator/clone-impl-async.stderr
@@ -1,83 +1,83 @@
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:17:16
    |
 LL |     check_copy(&inner_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:19:17
    |
 LL |     check_clone(&inner_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:12:27: 16:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:26:16
    |
 LL |     check_copy(&outer_non_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:28:17
    |
 LL |     check_clone(&outer_non_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:23:27: 25:6]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Copy` is not satisfied
   --> $DIR/clone-impl-async.rs:32:16
    |
 LL |     check_copy(&maybe_copy_clone);
-   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |     ---------- ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
 
-error[E0277]: the trait bound `impl Future<Output = ()>: Clone` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]: Clone` is not satisfied
   --> $DIR/clone-impl-async.rs:34:17
    |
 LL |     check_clone(&maybe_copy_clone);
-   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl Future<Output = ()>`
+   |     ----------- ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `[async block@$DIR/clone-impl-async.rs:31:28: 31:41]`
    |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -91,7 +91,7 @@ LL |     check_copy(&inner_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -105,7 +105,7 @@ LL |     check_clone(&inner_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -119,7 +119,7 @@ LL |     check_copy(&outer_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -133,7 +133,7 @@ LL |     check_clone(&outer_non_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
@@ -147,7 +147,7 @@ LL |     check_copy(&maybe_copy_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_copy`
-  --> $DIR/clone-impl-async.rs:70:18
+  --> $DIR/clone-impl-async.rs:69:18
    |
 LL | fn check_copy<T: Copy>(_x: &T) {}
    |                  ^^^^ required by this bound in `check_copy`
@@ -161,7 +161,7 @@ LL |     check_clone(&maybe_copy_clone_fn);
    |     required by a bound introduced by this call
    |
 note: required by a bound in `check_clone`
-  --> $DIR/clone-impl-async.rs:71:19
+  --> $DIR/clone-impl-async.rs:70:19
    |
 LL | fn check_clone<T: Clone>(_x: &T) {}
    |                   ^^^^^ required by this bound in `check_clone`
diff --git a/src/test/ui/impl-trait/issue-55872-3.rs b/src/test/ui/impl-trait/issue-55872-3.rs
index 3ffce85e61b..91811df93cd 100644
--- a/src/test/ui/impl-trait/issue-55872-3.rs
+++ b/src/test/ui/impl-trait/issue-55872-3.rs
@@ -12,7 +12,7 @@ pub trait Bar {
 impl<S> Bar for S {
     type E = impl std::marker::Copy;
     fn foo<T>() -> Self::E {
-    //~^ ERROR the trait bound `impl Future<Output = ()>: Copy` is not satisfied [E0277]
+        //~^ ERROR : Copy` is not satisfied [E0277]
         async {}
     }
 }
diff --git a/src/test/ui/impl-trait/issue-55872-3.stderr b/src/test/ui/impl-trait/issue-55872-3.stderr
index 6ab540e8751..c6e10f0f350 100644
--- a/src/test/ui/impl-trait/issue-55872-3.stderr
+++ b/src/test/ui/impl-trait/issue-55872-3.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `impl Future<Output = ()>: Copy` is not satisfied
+error[E0277]: the trait bound `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]: Copy` is not satisfied
   --> $DIR/issue-55872-3.rs:14:20
    |
 LL |     fn foo<T>() -> Self::E {
-   |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = ()>`
+   |                    ^^^^^^^ the trait `Copy` is not implemented for `[async block@$DIR/issue-55872-3.rs:16:9: 16:17]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
index 9ee1ba3d3b4..78233f300bd 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.rs
+++ b/src/test/ui/impl-trait/issues/issue-78722.rs
@@ -7,7 +7,7 @@ type F = impl core::future::Future<Output = u8>;
 struct Bug {
     V1: [(); {
         fn concrete_use() -> F {
-            //~^ ERROR expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
+            //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
             async {}
         }
         let f: F = async { 1 };
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
index a96994f5a7f..c00df8087e8 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.stderr
+++ b/src/test/ui/impl-trait/issues/issue-78722.stderr
@@ -16,7 +16,7 @@ LL |         let f: F = async { 1 };
 LL |     }],
    |     - value is dropped here
 
-error[E0271]: expected `impl Future<Output = ()>` to be a future that resolves to `u8`, but it resolves to `()`
+error[E0271]: expected `[async block@$DIR/issue-78722.rs:11:13: 11:21]` to be a future that resolves to `u8`, but it resolves to `()`
   --> $DIR/issue-78722.rs:9:30
    |
 LL |         fn concrete_use() -> F {
diff --git a/src/test/ui/pattern/non-structural-match-types.stderr b/src/test/ui/pattern/non-structural-match-types.stderr
index 45e16264973..dea7c4695cc 100644
--- a/src/test/ui/pattern/non-structural-match-types.stderr
+++ b/src/test/ui/pattern/non-structural-match-types.stderr
@@ -4,7 +4,7 @@ error: `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]` cannot be used
 LL |         const { || {} } => {},
    |         ^^^^^^^^^^^^^^^
 
-error: `impl Future<Output = ()>` cannot be used in patterns
+error: `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]` cannot be used in patterns
   --> $DIR/non-structural-match-types.rs:12:9
    |
 LL |         const { async {} } => {},
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 918d37e6559..34ff59a9bb0 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -87,7 +87,7 @@ LL | |     }
    |       arguments to this function are incorrect
    |
    = note:     expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
-           found `async` block `impl Future<Output = {integer}>`
+           found `async` block `[async block@$DIR/expected-boxed-future-isnt-pinned.rs:28:5: 30:6]`
 note: function defined here
   --> $SRC_DIR/core/src/future/mod.rs:LL:COL
    |
diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs
index 95ea8866609..70e7440f730 100644
--- a/src/tools/jsondoclint/src/json_find.rs
+++ b/src/tools/jsondoclint/src/json_find.rs
@@ -2,7 +2,7 @@ use std::fmt::Write;
 
 use serde_json::Value;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub enum SelectorPart {
     Field(String),
     Index(usize),
@@ -72,3 +72,6 @@ fn find_selector_recursive(
         }
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/src/tools/jsondoclint/src/json_find/tests.rs b/src/tools/jsondoclint/src/json_find/tests.rs
new file mode 100644
index 00000000000..2a533530714
--- /dev/null
+++ b/src/tools/jsondoclint/src/json_find/tests.rs
@@ -0,0 +1,27 @@
+use super::*;
+
+#[test]
+fn basic_find() {
+    use SelectorPart::*;
+
+    let j = serde_json::json!({
+        "index": {
+            "4": {
+                "inner": {
+                    "items": ["1", "2", "3"]
+                }
+            }
+        }
+    });
+
+    let sel = find_selector(&j, &serde_json::json!("1"));
+    let exp: Vec<Vec<SelectorPart>> = vec![vec![
+        Field("index".to_owned()),
+        Field("4".to_owned()),
+        Field("inner".to_owned()),
+        Field("items".to_owned()),
+        Index(0),
+    ]];
+
+    assert_eq!(exp, sel);
+}
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index 70d7a82a576..fc54c421b4b 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -9,13 +9,13 @@ pub(crate) mod item_kind;
 mod json_find;
 mod validator;
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 struct Error {
     kind: ErrorKind,
     id: Id,
 }
 
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
 enum ErrorKind {
     NotFound,
     Custom(String),
diff --git a/triagebot.toml b/triagebot.toml
index 985e065652d..133fbaede21 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -15,7 +15,7 @@ allow-unauthenticated = [
     "llvm-main",
     "needs-fcp",
     "relnotes",
-    "requires-nightly",
+    "requires-*",
     "regression-*",
     "perf-*",
     "AsyncAwait-OnDeck",
@@ -334,6 +334,13 @@ cc = ["@rust-lang/wg-mir-opt"]
 message = "Some changes occurred in const_evaluatable.rs"
 cc = ["@lcnr"]
 
+[mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
+message = """
+Some changes occurred in engine.rs, potentially modifying the public API \
+of `ObligationCtxt`.
+"""
+cc = ["@lcnr"]
+
 [mentions."compiler/rustc_error_codes/src/error_codes.rs"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]