diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index fee5d04cdae85..b62840d4bc822 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -112,7 +112,7 @@ pub fn expand_test_or_bench(
     };
 
     // Note: non-associated fn items are already handled by `expand_test_or_bench`
-    if !matches!(item.kind, ast::ItemKind::Fn(_)) {
+    let ast::ItemKind::Fn(fn_) = &item.kind else {
         let diag = &cx.sess.parse_sess.span_diagnostic;
         let msg = "the `#[test]` attribute may only be used on a non-associated function";
         let mut err = match item.kind {
@@ -130,7 +130,7 @@ pub fn expand_test_or_bench(
             .emit();
 
         return vec![Annotatable::Item(item)];
-    }
+    };
 
     // has_*_signature will report any errors in the type so compilation
     // will fail. We shouldn't try to expand in this case because the errors
@@ -141,12 +141,14 @@ pub fn expand_test_or_bench(
         return vec![Annotatable::Item(item)];
     }
 
-    let (sp, attr_sp) = (cx.with_def_site_ctxt(item.span), cx.with_def_site_ctxt(attr_sp));
+    let sp = cx.with_def_site_ctxt(item.span);
+    let ret_ty_sp = cx.with_def_site_ctxt(fn_.sig.decl.output.span());
+    let attr_sp = cx.with_def_site_ctxt(attr_sp);
 
     let test_id = Ident::new(sym::test, attr_sp);
 
     // creates test::$name
-    let test_path = |name| cx.path(sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
+    let test_path = |name| cx.path(ret_ty_sp, vec![test_id, Ident::from_str_and_span(name, sp)]);
 
     // creates test::ShouldPanic::$name
     let should_panic_path = |name| {
@@ -192,7 +194,7 @@ pub fn expand_test_or_bench(
                         vec![
                             // super::$test_fn(b)
                             cx.expr_call(
-                                sp,
+                                ret_ty_sp,
                                 cx.expr_path(cx.path(sp, vec![item.ident])),
                                 vec![cx.expr_ident(sp, b)],
                             ),
@@ -216,7 +218,11 @@ pub fn expand_test_or_bench(
                         cx.expr_path(test_path("assert_test_result")),
                         vec![
                             // $test_fn()
-                            cx.expr_call(sp, cx.expr_path(cx.path(sp, vec![item.ident])), vec![]), // )
+                            cx.expr_call(
+                                ret_ty_sp,
+                                cx.expr_path(cx.path(sp, vec![item.ident])),
+                                vec![],
+                            ), // )
                         ],
                     ), // }
                 ), // )
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 825011941a241..cf590a43826e5 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -340,17 +340,26 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
 
             sym::black_box => {
                 args[0].val.store(self, result);
-
+                let result_val_span = [result.llval];
                 // We need to "use" the argument in some way LLVM can't introspect, and on
                 // targets that support it we can typically leverage inline assembly to do
                 // this. LLVM's interpretation of inline assembly is that it's, well, a black
                 // box. This isn't the greatest implementation since it probably deoptimizes
                 // more than we want, but it's so far good enough.
+                //
+                // For zero-sized types, the location pointed to by the result may be
+                // uninitialized. Do not "use" the result in this case; instead just clobber
+                // the memory.
+                let (constraint, inputs): (&str, &[_]) = if result.layout.is_zst() {
+                    ("~{memory}", &[])
+                } else {
+                    ("r,~{memory}", &result_val_span)
+                };
                 crate::asm::inline_asm_call(
                     self,
                     "",
-                    "r,~{memory}",
-                    &[result.llval],
+                    constraint,
+                    inputs,
                     self.type_void(),
                     true,
                     false,
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index c49b19bdf0094..7f0c2861f7e29 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1260,11 +1260,11 @@ impl<'a> Linker for WasmLd<'a> {
     }
 
     fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
-        self.cmd.arg("-l").arg(lib);
+        self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive");
     }
 
     fn link_whole_rlib(&mut self, lib: &Path) {
-        self.cmd.arg(lib);
+        self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
     }
 
     fn gc_sections(&mut self, _keep_metadata: bool) {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0706.md b/compiler/rustc_error_codes/src/error_codes/E0706.md
index d379b8a2384c6..fabd855a222f0 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0706.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0706.md
@@ -56,4 +56,4 @@ You might be interested in visiting the [async book] for further information.
 [`async-trait` crate]: https://crates.io/crates/async-trait
 [async-is-hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
 [Generic Associated Types]: https://github.com/rust-lang/rust/issues/44265
-[async book]: https://rust-lang.github.io/async-book/07_workarounds/06_async_in_traits.html
+[async book]: https://rust-lang.github.io/async-book/07_workarounds/05_async_in_traits.html
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 46706e4984451..ff0fb9bae9232 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::util::elaborate_predicates_with_span;
 use rustc_middle::ty::adjustment;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, DefIdTree, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
@@ -87,17 +87,33 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'tcx> LateLintPass<'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
-        let expr = match s.kind {
-            hir::StmtKind::Semi(ref expr) => &**expr,
-            _ => return,
-        };
+        let hir::StmtKind::Semi(expr) = s.kind else { return; };
 
         if let hir::ExprKind::Ret(..) = expr.kind {
             return;
         }
 
+        if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind
+            && let ty = cx.typeck_results().expr_ty(&await_expr)
+            && let ty::Opaque(future_def_id, _) = ty.kind()
+            && cx.tcx.ty_is_opaque_future(ty)
+            // FIXME: This also includes non-async fns that return `impl Future`.
+            && let async_fn_def_id = cx.tcx.parent(*future_def_id)
+            && check_must_use_def(
+                cx,
+                async_fn_def_id,
+                expr.span,
+                "output of future returned by ",
+                "",
+            )
+        {
+            // We have a bare `foo().await;` on an opaque type from an async function that was
+            // annotated with `#[must_use]`.
+            return;
+        }
+
         let ty = cx.typeck_results().expr_ty(&expr);
-        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", 1);
+        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, expr.span, "", "", 1);
 
         let mut fn_warned = false;
         let mut op_warned = false;
@@ -119,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             _ => None,
         };
         if let Some(def_id) = maybe_def_id {
-            fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", "");
+            fn_warned = check_must_use_def(cx, def_id, expr.span, "return value of ", "");
         } else if type_permits_lack_of_use {
             // We don't warn about unused unit or uninhabited types.
             // (See https://github.com/rust-lang/rust/issues/43806 for details.)
@@ -565,10 +581,24 @@ trait UnusedDelimLint {
             lint.set_arg("delim", Self::DELIM_STR);
             lint.set_arg("item", msg);
             if let Some((lo, hi)) = spans {
-                let replacement = vec![
-                    (lo, if keep_space.0 { " ".into() } else { "".into() }),
-                    (hi, if keep_space.1 { " ".into() } else { "".into() }),
-                ];
+                let sm = cx.sess().source_map();
+                let lo_replace =
+                    if keep_space.0 &&
+                        let Ok(snip) = sm.span_to_prev_source(lo) && !snip.ends_with(" ") {
+                        " ".to_string()
+                        } else {
+                            "".to_string()
+                        };
+
+                let hi_replace =
+                    if keep_space.1 &&
+                        let Ok(snip) = sm.span_to_next_source(hi) && !snip.starts_with(" ") {
+                        " ".to_string()
+                        } else {
+                            "".to_string()
+                        };
+
+                let replacement = vec![(lo, lo_replace), (hi, hi_replace)];
                 lint.multipart_suggestion(
                     fluent::suggestion,
                     replacement,
@@ -765,6 +795,7 @@ impl UnusedParens {
         value: &ast::Pat,
         avoid_or: bool,
         avoid_mut: bool,
+        keep_space: (bool, bool),
     ) {
         use ast::{BindingAnnotation, PatKind};
 
@@ -789,7 +820,7 @@ impl UnusedParens {
             } else {
                 None
             };
-            self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
+            self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space);
         }
     }
 }
@@ -798,7 +829,7 @@ impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         match e.kind {
             ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
-                self.check_unused_parens_pat(cx, pat, false, false);
+                self.check_unused_parens_pat(cx, pat, false, false, (true, true));
             }
             // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already
             // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still
@@ -842,6 +873,7 @@ impl EarlyLintPass for UnusedParens {
 
     fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
         use ast::{Mutability, PatKind::*};
+        let keep_space = (false, false);
         match &p.kind {
             // Do not lint on `(..)` as that will result in the other arms being useless.
             Paren(_)
@@ -849,33 +881,33 @@ impl EarlyLintPass for UnusedParens {
             | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
             // These are list-like patterns; parens can always be removed.
             TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
-                self.check_unused_parens_pat(cx, p, false, false);
+                self.check_unused_parens_pat(cx, p, false, false, keep_space);
             },
             Struct(_, _, fps, _) => for f in fps {
-                self.check_unused_parens_pat(cx, &f.pat, false, false);
+                self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space);
             },
             // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106.
-            Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false),
+            Ident(.., Some(p)) | Box(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space),
             // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342.
             // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106.
-            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not),
+            Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space),
         }
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
         if let StmtKind::Local(ref local) = s.kind {
-            self.check_unused_parens_pat(cx, &local.pat, true, false);
+            self.check_unused_parens_pat(cx, &local.pat, true, false, (false, false));
         }
 
         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
     }
 
     fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
-        self.check_unused_parens_pat(cx, &param.pat, true, false);
+        self.check_unused_parens_pat(cx, &param.pat, true, false, (false, false));
     }
 
     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
-        self.check_unused_parens_pat(cx, &arm.pat, false, false);
+        self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false));
     }
 
     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index e3acc11811f42..d59982f7063f3 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1165,10 +1165,12 @@ pub(crate) struct ParenthesesInForHead {
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
 pub(crate) struct ParenthesesInForHeadSugg {
-    #[suggestion_part(code = "")]
+    #[suggestion_part(code = "{left_snippet}")]
     pub left: Span,
-    #[suggestion_part(code = "")]
+    pub left_snippet: String,
+    #[suggestion_part(code = "{right_snippet}")]
     pub right: Span,
+    pub right_snippet: String,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index c609aa93da3a7..0bbe073fe2af4 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1653,15 +1653,29 @@ impl<'a> Parser<'a> {
             (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
                 self.bump();
 
+                let sm = self.sess.source_map();
+                let left = begin_par_sp;
+                let right = self.prev_token.span;
+                let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) &&
+                        !snip.ends_with(" ") {
+                                " ".to_string()
+                            } else {
+                                "".to_string()
+                            };
+
+                let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) &&
+                        !snip.starts_with(" ") {
+                                " ".to_string()
+                            } else {
+                                "".to_string()
+                        };
+
                 self.sess.emit_err(ParenthesesInForHead {
-                    span: vec![begin_par_sp, self.prev_token.span],
+                    span: vec![left, right],
                     // With e.g. `for (x) in y)` this would replace `(x) in y)`
                     // with `x) in y)` which is syntactically invalid.
                     // However, this is prevented before we get here.
-                    sugg: ParenthesesInForHeadSugg {
-                        left: begin_par_sp,
-                        right: self.prev_token.span,
-                    },
+                    sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet },
                 });
 
                 // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 27a57adf964a3..e0da0096c4e1e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -139,7 +139,7 @@ impl CheckAttrVisitor<'_> {
                 sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
                 sym::const_trait => self.check_const_trait(attr, span, target),
                 sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
-                sym::must_use => self.check_must_use(hir_id, &attr, span, target),
+                sym::must_use => self.check_must_use(hir_id, &attr, target),
                 sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
                 sym::rustc_allow_incoherent_impl => {
                     self.check_allow_incoherent_impl(&attr, span, target)
@@ -1163,17 +1163,7 @@ impl CheckAttrVisitor<'_> {
     }
 
     /// Warns against some misuses of `#[must_use]`
-    fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
-        let node = self.tcx.hir().get(hir_id);
-        if let Some(kind) = node.fn_kind() && let rustc_hir::IsAsync::Async = kind.asyncness() {
-            self.tcx.emit_spanned_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr.span,
-                errors::MustUseAsync { span }
-            );
-        }
-
+    fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
         if !matches!(
             target,
             Target::Fn
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 2587a9c4b3498..f2bfec5a2a38a 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -219,26 +219,26 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             let (mod_prefix, mod_str, suggestion) = if path.len() == 1 {
                 debug!(?self.diagnostic_metadata.current_impl_items);
                 debug!(?self.diagnostic_metadata.current_function);
-                let suggestion = if let Some(items) = self.diagnostic_metadata.current_impl_items
+                let suggestion = if self.current_trait_ref.is_none()
                     && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function
-                    && self.current_trait_ref.is_none()
                     && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
+                    && let Some(items) = self.diagnostic_metadata.current_impl_items
                     && let Some(item) = items.iter().find(|i| {
-                        if let AssocItemKind::Fn(fn_) = &i.kind
-                            && !fn_.sig.decl.has_self()
-                            && i.ident.name == item_str.name
+                        if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
                         {
                             debug!(?item_str.name);
-                            debug!(?fn_.sig.decl.inputs);
                             return true
                         }
                         false
                     })
+                    && let AssocItemKind::Fn(fn_) = &item.kind
                 {
+                    debug!(?fn_);
+                    let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
                     Some((
-                        item_span,
+                        item_span.shrink_to_lo(),
                         "consider using the associated function",
-                        format!("Self::{}", item.ident)
+                        self_sugg.to_string()
                     ))
                 } else {
                     None
@@ -396,11 +396,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
     }
 
     fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) {
-        let is_assoc_fn = self.self_type_is_available();
+        if !self.self_type_is_available() {
+            return;
+        }
         let Some(path_last_segment) = path.last() else { return };
         let item_str = path_last_segment.ident;
         // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
-        if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn {
+        if ["this", "my"].contains(&item_str.as_str()) {
             err.span_suggestion_short(
                 span,
                 "you might have meant to use `self` here instead",
@@ -451,7 +453,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
         let path_str = Segment::names_to_string(path);
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
-
         let mut candidates = self
             .r
             .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
@@ -1542,7 +1543,6 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 _ => None,
             }
         }
-
         // Fields are generally expected in the same contexts as locals.
         if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
             if let Some(node_id) =
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index a5c3d35b1b594..39e2a90222670 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -107,10 +107,6 @@ impl Buffer {
         self.buffer
     }
 
-    pub(crate) fn insert_str(&mut self, idx: usize, s: &str) {
-        self.buffer.insert_str(idx, s);
-    }
-
     pub(crate) fn push_str(&mut self, s: &str) {
         self.buffer.push_str(s);
     }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 51843a505f709..73690c86f4f72 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -69,11 +69,13 @@ pub(crate) struct Context<'tcx> {
     /// the source files are present in the html rendering, then this will be
     /// `true`.
     pub(crate) include_sources: bool,
+    /// Collection of all types with notable traits referenced in the current module.
+    pub(crate) types_with_notable_traits: FxHashSet<clean::Type>,
 }
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
 #[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 128);
+rustc_data_structures::static_assert_size!(Context<'_>, 160);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
 pub(crate) struct SharedContext<'tcx> {
@@ -532,6 +534,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             deref_id_map: FxHashMap::default(),
             shared: Rc::new(scx),
             include_sources,
+            types_with_notable_traits: FxHashSet::default(),
         };
 
         if emit_crate {
@@ -560,6 +563,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             id_map: IdMap::new(),
             shared: Rc::clone(&self.shared),
             include_sources: self.include_sources,
+            types_with_notable_traits: FxHashSet::default(),
         }
     }
 
@@ -803,6 +807,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                 }
             }
         }
+
         Ok(())
     }
 
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 3a041ae15d618..fffd90c51fad1 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -59,7 +59,7 @@ use rustc_span::{
     symbol::{sym, Symbol},
     BytePos, FileName, RealFileName,
 };
-use serde::ser::SerializeSeq;
+use serde::ser::{SerializeMap, SerializeSeq};
 use serde::{Serialize, Serializer};
 
 use crate::clean::{self, ItemId, RenderedLink, SelfTy};
@@ -803,7 +803,7 @@ fn assoc_method(
     d: &clean::FnDecl,
     link: AssocItemLink<'_>,
     parent: ItemType,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     render_mode: RenderMode,
 ) {
     let tcx = cx.tcx();
@@ -836,6 +836,8 @@ fn assoc_method(
         + name.as_str().len()
         + generics_len;
 
+    let notable_traits = d.output.as_return().and_then(|output| notable_traits_button(output, cx));
+
     let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
         header_len += 4;
         let indent_str = "    ";
@@ -861,9 +863,9 @@ fn assoc_method(
         name = name,
         generics = g.print(cx),
         decl = d.full_print(header_len, indent, cx),
-        notable_traits = notable_traits_decl(d, cx),
+        notable_traits = notable_traits.unwrap_or_default(),
         where_clause = print_where_clause(g, cx, indent, end_newline),
-    )
+    );
 }
 
 /// Writes a span containing the versions at which an item became stable and/or const-stable. For
@@ -963,7 +965,7 @@ fn render_assoc_item(
     item: &clean::Item,
     link: AssocItemLink<'_>,
     parent: ItemType,
-    cx: &Context<'_>,
+    cx: &mut Context<'_>,
     render_mode: RenderMode,
 ) {
     match &*item.kind {
@@ -1273,88 +1275,135 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
     }
 }
 
-fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
-    let mut out = Buffer::html();
+pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
+    let mut has_notable_trait = false;
+
+    let did = ty.def_id(cx.cache())?;
 
-    if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
+    // Box has pass-through impls for Read, Write, Iterator, and Future when the
+    // boxed type implements one of those. We don't want to treat every Box return
+    // as being notably an Iterator (etc), though, so we exempt it. Pin has the same
+    // issue, with a pass-through impl for Future.
+    if Some(did) == cx.tcx().lang_items().owned_box()
+        || Some(did) == cx.tcx().lang_items().pin_type()
     {
-        // Box has pass-through impls for Read, Write, Iterator, and Future when the
-        // boxed type implements one of those. We don't want to treat every Box return
-        // as being notably an Iterator (etc), though, so we exempt it. Pin has the same
-        // issue, with a pass-through impl for Future.
-        if Some(did) == cx.tcx().lang_items().owned_box()
-            || Some(did) == cx.tcx().lang_items().pin_type()
-        {
-            return "".to_string();
-        }
-        if let Some(impls) = cx.cache().impls.get(&did) {
-            for i in impls {
-                let impl_ = i.inner_impl();
-                if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache())
+        return None;
+    }
+
+    if let Some(impls) = cx.cache().impls.get(&did) {
+        for i in impls {
+            let impl_ = i.inner_impl();
+            if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) {
+                // Two different types might have the same did,
+                // without actually being the same.
+                continue;
+            }
+            if let Some(trait_) = &impl_.trait_ {
+                let trait_did = trait_.def_id();
+
+                if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx()))
                 {
-                    // Two different types might have the same did,
-                    // without actually being the same.
-                    continue;
+                    has_notable_trait = true;
+                }
+            }
+        }
+    }
+
+    if has_notable_trait {
+        cx.types_with_notable_traits.insert(ty.clone());
+        Some(format!(
+            "<span class=\"notable-traits\" data-ty=\"{ty:#}\">\
+                <span class=\"notable-traits-tooltip\">ⓘ</span>\
+            </span>",
+            ty = ty.print(cx),
+        ))
+    } else {
+        None
+    }
+}
+
+fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
+    let mut out = Buffer::html();
+
+    let did = ty.def_id(cx.cache()).expect("notable_traits_button already checked this");
+
+    let impls = cx.cache().impls.get(&did).expect("notable_traits_button already checked this");
+
+    for i in impls {
+        let impl_ = i.inner_impl();
+        if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) {
+            // Two different types might have the same did,
+            // without actually being the same.
+            continue;
+        }
+        if let Some(trait_) = &impl_.trait_ {
+            let trait_did = trait_.def_id();
+
+            if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) {
+                if out.is_empty() {
+                    write!(
+                        &mut out,
+                        "<h3 class=\"notable\">Notable traits for <code>{}</code></h3>\
+                     <pre class=\"content\"><code>",
+                        impl_.for_.print(cx)
+                    );
                 }
-                if let Some(trait_) = &impl_.trait_ {
-                    let trait_did = trait_.def_id();
-
-                    if cx
-                        .cache()
-                        .traits
-                        .get(&trait_did)
-                        .map_or(false, |t| t.is_notable_trait(cx.tcx()))
-                    {
-                        if out.is_empty() {
-                            write!(
-                                &mut out,
-                                "<span class=\"notable\">Notable traits for {}</span>\
-                             <code class=\"content\">",
-                                impl_.for_.print(cx)
-                            );
-                        }
 
-                        //use the "where" class here to make it small
-                        write!(
+                //use the "where" class here to make it small
+                write!(
+                    &mut out,
+                    "<span class=\"where fmt-newline\">{}</span>",
+                    impl_.print(false, cx)
+                );
+                for it in &impl_.items {
+                    if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
+                        out.push_str("<span class=\"where fmt-newline\">    ");
+                        let empty_set = FxHashSet::default();
+                        let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set);
+                        assoc_type(
                             &mut out,
-                            "<span class=\"where fmt-newline\">{}</span>",
-                            impl_.print(false, cx)
+                            it,
+                            &tydef.generics,
+                            &[], // intentionally leaving out bounds
+                            Some(&tydef.type_),
+                            src_link,
+                            0,
+                            cx,
                         );
-                        for it in &impl_.items {
-                            if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
-                                out.push_str("<span class=\"where fmt-newline\">    ");
-                                let empty_set = FxHashSet::default();
-                                let src_link =
-                                    AssocItemLink::GotoSource(trait_did.into(), &empty_set);
-                                assoc_type(
-                                    &mut out,
-                                    it,
-                                    &tydef.generics,
-                                    &[], // intentionally leaving out bounds
-                                    Some(&tydef.type_),
-                                    src_link,
-                                    0,
-                                    cx,
-                                );
-                                out.push_str(";</span>");
-                            }
-                        }
+                        out.push_str(";</span>");
                     }
                 }
             }
         }
     }
-
-    if !out.is_empty() {
-        out.insert_str(
-            0,
-            "<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ\
-            <span class=\"notable-traits-tooltiptext\"><span class=\"docblock\">",
-        );
-        out.push_str("</code></span></span></span></span>");
+    if out.is_empty() {
+        write!(&mut out, "</code></pre>",);
     }
 
-    out.into_inner()
+    (format!("{:#}", ty.print(cx)), out.into_inner())
+}
+
+pub(crate) fn notable_traits_json<'a>(
+    tys: impl Iterator<Item = &'a clean::Type>,
+    cx: &Context<'_>,
+) -> String {
+    let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect();
+    mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2));
+    struct NotableTraitsMap(Vec<(String, String)>);
+    impl Serialize for NotableTraitsMap {
+        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            let mut map = serializer.serialize_map(Some(self.0.len()))?;
+            for item in &self.0 {
+                map.serialize_entry(&item.0, &item.1)?;
+            }
+            map.end()
+        }
+    }
+    serde_json::to_string(&NotableTraitsMap(mp))
+        .expect("serialize (string, string) -> json object cannot fail")
 }
 
 #[derive(Clone, Copy, Debug)]
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index ce4fc4d68fac2..ac11a860a4f0b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -17,9 +17,10 @@ use std::rc::Rc;
 
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
-    item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item,
-    render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl,
-    render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters,
+    item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
+    render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
+    render_impl, render_rightside, render_stability_since_raw, AssocItemLink, Context,
+    ImplRenderingParameters,
 };
 use crate::clean;
 use crate::config::ModuleSorting;
@@ -183,6 +184,16 @@ pub(super) fn print_item(
             unreachable!();
         }
     }
+
+    // Render notable-traits.js used for all methods in this module.
+    if !cx.types_with_notable_traits.is_empty() {
+        write!(
+            buf,
+            r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
+            notable_traits_json(cx.types_with_notable_traits.iter(), cx)
+        );
+        cx.types_with_notable_traits.clear();
+    }
 }
 
 /// For large structs, enums, unions, etc, determine whether to hide their fields
@@ -516,6 +527,9 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
         + name.as_str().len()
         + generics_len;
 
+    let notable_traits =
+        f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
+
     wrap_into_item_decl(w, |w| {
         wrap_item(w, "fn", |w| {
             render_attributes_in_pre(w, it, "");
@@ -533,11 +547,11 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
                 generics = f.generics.print(cx),
                 where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
                 decl = f.decl.full_print(header_len, 0, cx),
-                notable_traits = notable_traits_decl(&f.decl, cx),
+                notable_traits = notable_traits.unwrap_or_default(),
             );
         });
     });
-    document(w, cx, it, None, HeadingOffset::H2)
+    document(w, cx, it, None, HeadingOffset::H2);
 }
 
 fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 301f03a16427a..54e8b6561f34f 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -22,3 +22,9 @@ nav.sub {
 .source .sidebar {
 	display: none;
 }
+
+.notable-traits {
+	/* layout requires javascript
+	    https://github.com/rust-lang/rust/issues/102576 */
+	display: none;
+}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 86a5b0b303f39..9a30240c7bac3 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -183,6 +183,8 @@ h4.code-header {
 	font-weight: 600;
 	margin: 0;
 	padding: 0;
+	/* position notable traits in mobile mode within the header */
+	position: relative;
 }
 
 #crate-search,
@@ -1276,13 +1278,12 @@ h3.variant {
 	cursor: pointer;
 }
 
-.notable-traits:hover .notable-traits-tooltiptext,
-.notable-traits .notable-traits-tooltiptext.force-tooltip {
+.notable-traits .notable-traits-tooltiptext {
 	display: inline-block;
+	visibility: hidden;
 }
 
-.notable-traits .notable-traits-tooltiptext {
-	display: none;
+.notable-traits-tooltiptext {
 	padding: 5px 3px 3px 3px;
 	border-radius: 6px;
 	margin-left: 5px;
@@ -1300,22 +1301,26 @@ h3.variant {
 	content: "\00a0\00a0\00a0";
 }
 
-.notable-traits .docblock {
+.notable-traits-tooltiptext .docblock {
 	margin: 0;
 }
 
-.notable-traits .notable {
-	margin: 0;
-	margin-bottom: 13px;
+.notable-traits-tooltiptext .notable {
 	font-size: 1.1875rem;
 	font-weight: 600;
 	display: block;
 }
 
-.notable-traits .docblock code.content {
+.notable-traits-tooltiptext pre, .notable-traits-tooltiptext code {
+	background: transparent;
+}
+
+.notable-traits-tooltiptext .docblock pre.content {
 	margin: 0;
 	padding: 0;
 	font-size: 1.25rem;
+	white-space: pre-wrap;
+	overflow: hidden;
 }
 
 .search-failed {
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 1c84393cb4e6f..0426774e80d46 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -790,6 +790,19 @@ function loadCss(cssUrl) {
             // we need to switch away from mobile mode and make the main content area scrollable.
             hideSidebar();
         }
+        if (window.CURRENT_NOTABLE_ELEMENT) {
+            // As a workaround to the behavior of `contains: layout` used in doc togglers, the
+            // notable traits popup is positioned using javascript.
+            //
+            // This means when the window is resized, we need to redo the layout.
+            const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE;
+            const force_visible = base.NOTABLE_FORCE_VISIBLE;
+            hideNotable();
+            if (force_visible) {
+                showNotable(base);
+                base.NOTABLE_FORCE_VISIBLE = true;
+            }
+        }
     });
 
     function handleClick(id, f) {
@@ -822,10 +835,80 @@ function loadCss(cssUrl) {
         });
     });
 
+    function showNotable(e) {
+        if (!window.NOTABLE_TRAITS) {
+            const data = document.getElementById("notable-traits-data");
+            if (data) {
+                window.NOTABLE_TRAITS = JSON.parse(data.innerText);
+            } else {
+                throw new Error("showNotable() called on page without any notable traits!");
+            }
+        }
+        if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) {
+            // Make this function idempotent.
+            return;
+        }
+        hideNotable();
+        const ty = e.getAttribute("data-ty");
+        const tooltip = e.getElementsByClassName("notable-traits-tooltip")[0];
+        const wrapper = document.createElement("div");
+        wrapper.innerHTML = "<div class=\"docblock\">" + window.NOTABLE_TRAITS[ty] + "</div>";
+        wrapper.className = "notable-traits-tooltiptext";
+        tooltip.appendChild(wrapper);
+        const pos = wrapper.getBoundingClientRect();
+        tooltip.removeChild(wrapper);
+        wrapper.style.top = (pos.top + window.scrollY) + "px";
+        wrapper.style.left = (pos.left + window.scrollX) + "px";
+        wrapper.style.width = pos.width + "px";
+        const body = document.getElementsByTagName("body")[0];
+        body.appendChild(wrapper);
+        window.CURRENT_NOTABLE_ELEMENT = wrapper;
+        window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e;
+        wrapper.onpointerleave = function(ev) {
+            // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+            if (ev.pointerType !== "mouse") {
+                return;
+            }
+            if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
+                hideNotable();
+            }
+        };
+    }
+
+    function hideNotable() {
+        if (window.CURRENT_NOTABLE_ELEMENT) {
+            window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false;
+            const body = document.getElementsByTagName("body")[0];
+            body.removeChild(window.CURRENT_NOTABLE_ELEMENT);
+            window.CURRENT_NOTABLE_ELEMENT = null;
+        }
+    }
+
     onEachLazy(document.getElementsByClassName("notable-traits"), e => {
         e.onclick = function() {
-            this.getElementsByClassName("notable-traits-tooltiptext")[0]
-                .classList.toggle("force-tooltip");
+            this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true;
+            if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) {
+                hideNotable();
+            } else {
+                showNotable(this);
+            }
+        };
+        e.onpointerenter = function(ev) {
+            // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+            if (ev.pointerType !== "mouse") {
+                return;
+            }
+            showNotable(this);
+        };
+        e.onpointerleave = function(ev) {
+            // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+            if (ev.pointerType !== "mouse") {
+                return;
+            }
+            if (!this.NOTABLE_FORCE_VISIBLE &&
+                !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
+                hideNotable();
+            }
         };
     });
 
diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml
index efe0cb15f08a0..d8261d8dc902c 100644
--- a/src/test/rustdoc-gui/notable-trait.goml
+++ b/src/test/rustdoc-gui/notable-trait.goml
@@ -25,22 +25,28 @@ assert-position: (
     {"x": 951},
 )
 // The tooltip should be beside the `i`
+// Also, clicking the tooltip should bring its text into the DOM
+assert-count: ("//*[@class='notable-traits-tooltiptext']", 0)
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable-traits-tooltiptext']", 1)
 compare-elements-position-near: (
     "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+    "//*[@class='notable-traits-tooltiptext']",
     {"y": 2}
 )
 compare-elements-position-false: (
     "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+    "//*[@class='notable-traits-tooltiptext']",
     ("x")
 )
 // The docblock should be flush with the border.
 assert-css: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']",
+    "//*[@class='notable-traits-tooltiptext']/*[@class='docblock']",
     {"margin-left": "0px"}
 )
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+move-cursor-to: "//h1"
+assert-count: ("//*[@class='notable-traits-tooltiptext']", 0)
 
 // Now only the `i` should be on the next line.
 size: (1055, 600)
@@ -98,26 +104,31 @@ assert-position: (
     {"x": 289},
 )
 // The tooltip should be below `i`
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+assert-count: ("//*[@class='notable-traits-tooltiptext']", 1)
 compare-elements-position-near-false: (
     "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+    "//*[@class='notable-traits-tooltiptext']",
     {"y": 2}
 )
 compare-elements-position-false: (
     "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+    "//*[@class='notable-traits-tooltiptext']",
     ("x")
 )
 compare-elements-position-near: (
-    "//*[@id='method.create_an_iterator_from_read']/parent::*",
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
-    {"x": 5}
+    "//*[@id='method.create_an_iterator_from_read']",
+    "//*[@class='notable-traits-tooltiptext']",
+    {"x": 10}
 )
 // The docblock should be flush with the border.
 assert-css: (
-    "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']",
+    "//*[@class='notable-traits-tooltiptext']/*[@class='docblock']",
     {"margin-left": "0px"}
 )
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+move-cursor-to: "//h1"
+assert-count: ("//*[@class='notable-traits-tooltiptext']", 0)
 
 // Checking on very small mobile. The `i` should be on its own line.
 size: (365, 600)
@@ -126,3 +137,76 @@ compare-elements-position-false: (
     "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
     ("y", "x"),
 )
+
+// Now check the colors.
+define-function: (
+    "check-colors",
+    (theme, header_color, content_color, type_color, trait_color),
+    [
+        ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"),
+        // This is needed to ensure that the text color is computed.
+        ("show-text", true),
+
+        // Setting the theme.
+        ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+        // We reload the page so the local storage settings are being used.
+        ("reload"),
+
+        ("move-cursor-to", "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"),
+        ("assert-count", (".notable-traits-tooltiptext", 1)),
+
+        ("assert-css", (
+             ".notable-traits-tooltiptext h3.notable",
+             {"color": |header_color|},
+             ALL,
+        )),
+        ("assert-css", (
+             ".notable-traits-tooltiptext pre.content",
+             {"color": |content_color|},
+             ALL,
+        )),
+        ("assert-css", (
+             ".notable-traits-tooltiptext pre.content a.struct",
+             {"color": |type_color|},
+             ALL,
+        )),
+        ("assert-css", (
+             ".notable-traits-tooltiptext pre.content a.trait",
+             {"color": |trait_color|},
+             ALL,
+        )),
+    ]
+)
+
+call-function: (
+    "check-colors",
+    {
+        "theme": "ayu",
+        "content_color": "rgb(230, 225, 207)",
+        "header_color": "rgb(255, 255, 255)",
+        "type_color": "rgb(255, 160, 165)",
+        "trait_color": "rgb(57, 175, 215)",
+    },
+)
+
+call-function: (
+    "check-colors",
+    {
+        "theme": "dark",
+        "content_color": "rgb(221, 221, 221)",
+        "header_color": "rgb(221, 221, 221)",
+        "type_color": "rgb(45, 191, 184)",
+        "trait_color": "rgb(183, 140, 242)",
+    },
+)
+
+call-function: (
+    "check-colors",
+    {
+        "theme": "light",
+        "content_color": "rgb(0, 0, 0)",
+        "header_color": "rgb(0, 0, 0)",
+        "type_color": "rgb(173, 55, 138)",
+        "trait_color": "rgb(110, 79, 201)",
+    },
+)
diff --git a/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html b/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html
new file mode 100644
index 0000000000000..6b58be7e6853e
--- /dev/null
+++ b/src/test/rustdoc/doc-notable_trait-slice.bare_fn_matches.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"&amp;'static [SomeStruct]":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&amp;amp;[&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\"&gt;SomeStruct&lt;/a&gt;]&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait_slice::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &amp;amp;[&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait_slice::SomeStruct\"&gt;SomeStruct&lt;/a&gt;]&lt;/span&gt;"}</script>
\ No newline at end of file
diff --git a/src/test/rustdoc/doc-notable_trait-slice.rs b/src/test/rustdoc/doc-notable_trait-slice.rs
index b0d414027216a..2411da8cd4549 100644
--- a/src/test/rustdoc/doc-notable_trait-slice.rs
+++ b/src/test/rustdoc/doc-notable_trait-slice.rs
@@ -8,13 +8,13 @@ pub struct OtherStruct;
 impl SomeTrait for &[SomeStruct] {}
 
 // @has doc_notable_trait_slice/fn.bare_fn_matches.html
-// @has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+// @snapshot bare_fn_matches - '//script[@id="notable-traits-data"]'
 pub fn bare_fn_matches() -> &'static [SomeStruct] {
     &[]
 }
 
 // @has doc_notable_trait_slice/fn.bare_fn_no_matches.html
-// @!has - '//code[@class="content"]' 'impl SomeTrait for &[SomeStruct]'
+// @count - '//script[@id="notable-traits-data"]' 0
 pub fn bare_fn_no_matches() -> &'static [OtherStruct] {
     &[]
 }
diff --git a/src/test/rustdoc/doc-notable_trait.bare-fn.html b/src/test/rustdoc/doc-notable_trait.bare-fn.html
new file mode 100644
index 0000000000000..4e4a3f18f2498
--- /dev/null
+++ b/src/test/rustdoc/doc-notable_trait.bare-fn.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;"}</script>
\ No newline at end of file
diff --git a/src/test/rustdoc/doc-notable_trait.rs b/src/test/rustdoc/doc-notable_trait.rs
index 58a24b855d6e2..1f2cd7181c3d4 100644
--- a/src/test/rustdoc/doc-notable_trait.rs
+++ b/src/test/rustdoc/doc-notable_trait.rs
@@ -9,7 +9,8 @@ impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
 #[doc(notable_trait)]
 pub trait SomeTrait {
     // @has doc_notable_trait/trait.SomeTrait.html
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
+    // @has - '//span[@class="notable-traits"]/@data-ty' 'Wrapper<Self>'
+    // @snapshot wrap-me - '//script[@id="notable-traits-data"]'
     fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
         Wrapper {
             inner: self,
@@ -22,15 +23,16 @@ impl SomeTrait for SomeStruct {}
 
 impl SomeStruct {
     // @has doc_notable_trait/struct.SomeStruct.html
-    // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
-    // @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
+    // @has - '//span[@class="notable-traits"]/@data-ty' 'SomeStruct'
+    // @snapshot some-struct-new - '//script[@id="notable-traits-data"]'
     pub fn new() -> SomeStruct {
         SomeStruct
     }
 }
 
 // @has doc_notable_trait/fn.bare_fn.html
-// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
+// @has - '//span[@class="notable-traits"]/@data-ty' 'SomeStruct'
+// @snapshot bare-fn - '//script[@id="notable-traits-data"]'
 pub fn bare_fn() -> SomeStruct {
     SomeStruct
 }
diff --git a/src/test/rustdoc/doc-notable_trait.some-struct-new.html b/src/test/rustdoc/doc-notable_trait.some-struct-new.html
new file mode 100644
index 0000000000000..c0fd9748fd371
--- /dev/null
+++ b/src/test/rustdoc/doc-notable_trait.some-struct-new.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>
\ No newline at end of file
diff --git a/src/test/rustdoc/doc-notable_trait.wrap-me.html b/src/test/rustdoc/doc-notable_trait.wrap-me.html
new file mode 100644
index 0000000000000..9a59d5edd12a8
--- /dev/null
+++ b/src/test/rustdoc/doc-notable_trait.wrap-me.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script>
\ No newline at end of file
diff --git a/src/test/rustdoc/spotlight-from-dependency.odd.html b/src/test/rustdoc/spotlight-from-dependency.odd.html
new file mode 100644
index 0000000000000..987a949af44b1
--- /dev/null
+++ b/src/test/rustdoc/spotlight-from-dependency.odd.html
@@ -0,0 +1 @@
+<script type="text/json" id="notable-traits-data">{"Odd":"&lt;h3 class=\"notable\"&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\"&gt;Odd&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre class=\"content\"&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html\" title=\"trait core::iter::traits::iterator::Iterator\"&gt;Iterator&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Odd.html\" title=\"struct foo::Odd\"&gt;Odd&lt;/a&gt;&lt;/span&gt;&lt;span class=\"where fmt-newline\"&gt;    type &lt;a href=\"{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item\" class=\"associatedtype\"&gt;Item&lt;/a&gt; = &lt;a class=\"primitive\" href=\"{{channel}}/std/primitive.usize.html\"&gt;usize&lt;/a&gt;;&lt;/span&gt;"}</script>
\ No newline at end of file
diff --git a/src/test/rustdoc/spotlight-from-dependency.rs b/src/test/rustdoc/spotlight-from-dependency.rs
index 5245789212d8c..156aedca62b4e 100644
--- a/src/test/rustdoc/spotlight-from-dependency.rs
+++ b/src/test/rustdoc/spotlight-from-dependency.rs
@@ -3,7 +3,8 @@
 use std::iter::Iterator;
 
 // @has foo/struct.Odd.html
-// @has - '//*[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd'
+// @has - '//*[@id="method.new"]//span[@class="notable-traits"]/@data-ty' 'Odd'
+// @snapshot odd - '//script[@id="notable-traits-data"]'
 pub struct Odd {
     current: usize,
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
index 3840108597131..39ec71ba22a18 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
@@ -16,7 +16,7 @@ LL | /     || match out_ref {
 LL | |         Variant::A => (),
 LL | |         Variant::B => (),
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: closures are lazy and do nothing unless called
    = note: `#[warn(unused_must_use)]` on by default
@@ -28,7 +28,7 @@ LL | /     || match here.field {
 LL | |         Variant::A => (),
 LL | |         Variant::B => (),
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: closures are lazy and do nothing unless called
 
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
index 5f278f94b93bd..fbfcd45652f19 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr
@@ -28,7 +28,7 @@ warning: unused `MustUseDeprecated` that must be used
   --> $DIR/cfg-attr-multi-true.rs:19:5
    |
 LL |     MustUseDeprecated::new();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/cfg-attr-multi-true.rs:7:9
diff --git a/src/test/ui/generator/issue-52398.stderr b/src/test/ui/generator/issue-52398.stderr
index 30a6732f75956..539343275df60 100644
--- a/src/test/ui/generator/issue-52398.stderr
+++ b/src/test/ui/generator/issue-52398.stderr
@@ -4,7 +4,7 @@ warning: unused generator that must be used
 LL | /     move || {
 LL | |         A.test(yield);
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
@@ -16,7 +16,7 @@ LL | /     static move || {
 LL | |         yield *y.borrow();
 LL | |         return "Done";
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
 
diff --git a/src/test/ui/generator/issue-57084.stderr b/src/test/ui/generator/issue-57084.stderr
index 29aca94408a82..8f1fc5e803194 100644
--- a/src/test/ui/generator/issue-57084.stderr
+++ b/src/test/ui/generator/issue-57084.stderr
@@ -7,7 +7,7 @@ LL | |         loop {
 LL | |             yield
 LL | |         }
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/match-bindings.stderr b/src/test/ui/generator/match-bindings.stderr
index b911b6661909a..3dd2d595445aa 100644
--- a/src/test/ui/generator/match-bindings.stderr
+++ b/src/test/ui/generator/match-bindings.stderr
@@ -8,7 +8,7 @@ LL | |                 match Enum::A(String::new()) {
 ...  |
 LL | |         }
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/reborrow-mut-upvar.stderr b/src/test/ui/generator/reborrow-mut-upvar.stderr
index e83dbf833bfa7..2e1fec35eaf52 100644
--- a/src/test/ui/generator/reborrow-mut-upvar.stderr
+++ b/src/test/ui/generator/reborrow-mut-upvar.stderr
@@ -8,7 +8,7 @@ LL | |             yield;
 ...  |
 LL | |         *bar = 2;
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
index 5cb43067fee6b..e262f213f63d2 100644
--- a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
+++ b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
@@ -8,7 +8,7 @@ LL | |             // and it should also find out that `a` is not live.
 ...  |
 LL | |             let _ = &a;
 LL | |         };
-   | |__________^
+   | |_________^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/yield-in-args-rev.stderr b/src/test/ui/generator/yield-in-args-rev.stderr
index c9e1ab722d47f..a87248f662100 100644
--- a/src/test/ui/generator/yield-in-args-rev.stderr
+++ b/src/test/ui/generator/yield-in-args-rev.stderr
@@ -5,7 +5,7 @@ LL | /     || {
 LL | |         let b = true;
 LL | |         foo(yield, &b);
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr
index 8587e1dc663bc..9d03ee00800c8 100644
--- a/src/test/ui/generator/yield-in-box.stderr
+++ b/src/test/ui/generator/yield-in-box.stderr
@@ -8,7 +8,7 @@ LL | |             let _t = box (&x, yield 0, &y);
 ...  |
 LL | |         }
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/yield-in-initializer.stderr b/src/test/ui/generator/yield-in-initializer.stderr
index 07de24662cf2e..ed14a2e3273af 100644
--- a/src/test/ui/generator/yield-in-initializer.stderr
+++ b/src/test/ui/generator/yield-in-initializer.stderr
@@ -8,7 +8,7 @@ LL | |             // See https://github.com/rust-lang/rust/issues/52792
 ...  |
 LL | |         }
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/generator/yield-subtype.stderr b/src/test/ui/generator/yield-subtype.stderr
index fe10477bf7380..97862e91cd4a0 100644
--- a/src/test/ui/generator/yield-subtype.stderr
+++ b/src/test/ui/generator/yield-subtype.stderr
@@ -5,7 +5,7 @@ LL | /     || {
 LL | |         yield a;
 LL | |         yield b;
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/issues/issue-1460.stderr b/src/test/ui/issues/issue-1460.stderr
index f0ff2cafd4466..eb7661fad56db 100644
--- a/src/test/ui/issues/issue-1460.stderr
+++ b/src/test/ui/issues/issue-1460.stderr
@@ -2,7 +2,7 @@ warning: unused closure that must be used
   --> $DIR/issue-1460.rs:6:5
    |
 LL |     {|i: u32| if 1 == i { }};
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/issues/issue-16256.stderr b/src/test/ui/issues/issue-16256.stderr
index ca8e9a1bed337..d920530b57c69 100644
--- a/src/test/ui/issues/issue-16256.stderr
+++ b/src/test/ui/issues/issue-16256.stderr
@@ -2,7 +2,7 @@ warning: unused closure that must be used
   --> $DIR/issue-16256.rs:6:5
    |
 LL |     |c: u8| buf.push(c);
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr
index 2805720f035b8..657f23c60856f 100644
--- a/src/test/ui/lint/fn_must_use.stderr
+++ b/src/test/ui/lint/fn_must_use.stderr
@@ -2,7 +2,7 @@ warning: unused return value of `need_to_use_this_value` that must be used
   --> $DIR/fn_must_use.rs:55:5
    |
 LL |     need_to_use_this_value();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: it's important
 note: the lint level is defined here
@@ -15,13 +15,13 @@ warning: unused return value of `MyStruct::need_to_use_this_method_value` that m
   --> $DIR/fn_must_use.rs:60:5
    |
 LL |     m.need_to_use_this_method_value();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused return value of `EvenNature::is_even` that must be used
   --> $DIR/fn_must_use.rs:61:5
    |
 LL |     m.is_even(); // trait method!
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^
    |
    = note: no side effects
 
@@ -29,19 +29,19 @@ warning: unused return value of `MyStruct::need_to_use_this_associated_function_
   --> $DIR/fn_must_use.rs:64:5
    |
 LL |     MyStruct::need_to_use_this_associated_function_value();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused return value of `std::cmp::PartialEq::eq` that must be used
   --> $DIR/fn_must_use.rs:70:5
    |
 LL |     2.eq(&3);
-   |     ^^^^^^^^^
+   |     ^^^^^^^^
 
 warning: unused return value of `std::cmp::PartialEq::eq` that must be used
   --> $DIR/fn_must_use.rs:71:5
    |
 LL |     m.eq(&n);
-   |     ^^^^^^^^^
+   |     ^^^^^^^^
 
 warning: unused comparison that must be used
   --> $DIR/fn_must_use.rs:74:5
diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.fixed b/src/test/ui/lint/issue-103435-extra-parentheses.fixed
new file mode 100644
index 0000000000000..2b01b414baa6e
--- /dev/null
+++ b/src/test/ui/lint/issue-103435-extra-parentheses.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+#![deny(unused_parens)]
+
+fn main() {
+    if let Some(_) = Some(1) {}
+    //~^ ERROR unnecessary parentheses around pattern
+
+    for _x in 1..10 {}
+    //~^ ERROR unnecessary parentheses around pattern
+
+    if 2 == 1 {}
+    //~^ ERROR unnecessary parentheses around `if` condition
+
+    // reported by parser
+    for _x in 1..10 {}
+    //~^ ERROR expected one of
+    //~| ERROR unexpected parentheses surrounding
+}
diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.rs b/src/test/ui/lint/issue-103435-extra-parentheses.rs
new file mode 100644
index 0000000000000..8261610cf5646
--- /dev/null
+++ b/src/test/ui/lint/issue-103435-extra-parentheses.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+#![deny(unused_parens)]
+
+fn main() {
+    if let(Some(_))= Some(1) {}
+    //~^ ERROR unnecessary parentheses around pattern
+
+    for(_x)in 1..10 {}
+    //~^ ERROR unnecessary parentheses around pattern
+
+    if(2 == 1){}
+    //~^ ERROR unnecessary parentheses around `if` condition
+
+    // reported by parser
+    for(_x in 1..10){}
+    //~^ ERROR expected one of
+    //~| ERROR unexpected parentheses surrounding
+}
diff --git a/src/test/ui/lint/issue-103435-extra-parentheses.stderr b/src/test/ui/lint/issue-103435-extra-parentheses.stderr
new file mode 100644
index 0000000000000..29c41c91050b9
--- /dev/null
+++ b/src/test/ui/lint/issue-103435-extra-parentheses.stderr
@@ -0,0 +1,61 @@
+error: expected one of `)`, `,`, `@`, or `|`, found keyword `in`
+  --> $DIR/issue-103435-extra-parentheses.rs:15:12
+   |
+LL |     for(_x in 1..10){}
+   |            ^^ expected one of `)`, `,`, `@`, or `|`
+
+error: unexpected parentheses surrounding `for` loop head
+  --> $DIR/issue-103435-extra-parentheses.rs:15:8
+   |
+LL |     for(_x in 1..10){}
+   |        ^           ^
+   |
+help: remove parentheses in `for` loop
+   |
+LL -     for(_x in 1..10){}
+LL +     for _x in 1..10 {}
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-103435-extra-parentheses.rs:5:11
+   |
+LL |     if let(Some(_))= Some(1) {}
+   |           ^       ^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-103435-extra-parentheses.rs:2:9
+   |
+LL | #![deny(unused_parens)]
+   |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     if let(Some(_))= Some(1) {}
+LL +     if let Some(_) = Some(1) {}
+   |
+
+error: unnecessary parentheses around pattern
+  --> $DIR/issue-103435-extra-parentheses.rs:8:8
+   |
+LL |     for(_x)in 1..10 {}
+   |        ^  ^
+   |
+help: remove these parentheses
+   |
+LL -     for(_x)in 1..10 {}
+LL +     for _x in 1..10 {}
+   |
+
+error: unnecessary parentheses around `if` condition
+  --> $DIR/issue-103435-extra-parentheses.rs:11:7
+   |
+LL |     if(2 == 1){}
+   |       ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     if(2 == 1){}
+LL +     if 2 == 1 {}
+   |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
index 011acc3bf5d6e..72118275774d1 100644
--- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr
+++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
@@ -2,7 +2,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used
   --> $DIR/must-use-box-from-raw.rs:8:5
    |
 LL |     Box::from_raw(ptr);
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^
    |
    = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
 note: the lint level is defined here
diff --git a/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr
index 45a5317fccc6e..bba2b1ba078c6 100644
--- a/src/test/ui/lint/unused/must_use-array.stderr
+++ b/src/test/ui/lint/unused/must_use-array.stderr
@@ -2,7 +2,7 @@ error: unused array of `S` that must be used
   --> $DIR/must_use-array.rs:39:5
    |
 LL |     singleton();
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/must_use-array.rs:1:9
@@ -14,7 +14,7 @@ error: unused array of `S` that must be used
   --> $DIR/must_use-array.rs:40:5
    |
 LL |     many();
-   |     ^^^^^^^
+   |     ^^^^^^
 
 error: unused array of `S` in tuple element 0 that must be used
   --> $DIR/must_use-array.rs:41:6
@@ -26,7 +26,7 @@ error: unused array of implementers of `T` that must be used
   --> $DIR/must_use-array.rs:42:5
    |
 LL |     array_of_impl_trait();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: unused array of boxed `T` trait objects in tuple element 1 that must be used
   --> $DIR/must_use-array.rs:43:5
@@ -38,7 +38,7 @@ error: unused array of arrays of arrays of `S` that must be used
   --> $DIR/must_use-array.rs:45:5
    |
 LL |     array_of_arrays_of_arrays();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
index f5199f43c74bd..ef738708d5f4e 100644
--- a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
+++ b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
@@ -2,7 +2,7 @@ error: unused implementer of `Iterator` that must be used
   --> $DIR/must_use-in-stdlib-traits.rs:42:4
    |
 LL |    iterator();
-   |    ^^^^^^^^^^^
+   |    ^^^^^^^^^^
    |
    = note: iterators are lazy and do nothing unless consumed
 note: the lint level is defined here
@@ -15,7 +15,7 @@ error: unused implementer of `Future` that must be used
   --> $DIR/must_use-in-stdlib-traits.rs:43:4
    |
 LL |    future();
-   |    ^^^^^^^^^
+   |    ^^^^^^^^
    |
    = note: futures do nothing unless you `.await` or poll them
 
@@ -23,7 +23,7 @@ error: unused implementer of `FnOnce` that must be used
   --> $DIR/must_use-in-stdlib-traits.rs:44:4
    |
 LL |    square_fn_once();
-   |    ^^^^^^^^^^^^^^^^^
+   |    ^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -31,7 +31,7 @@ error: unused implementer of `FnMut` that must be used
   --> $DIR/must_use-in-stdlib-traits.rs:45:4
    |
 LL |    square_fn_mut();
-   |    ^^^^^^^^^^^^^^^^
+   |    ^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -39,7 +39,7 @@ error: unused implementer of `Fn` that must be used
   --> $DIR/must_use-in-stdlib-traits.rs:46:4
    |
 LL |    square_fn();
-   |    ^^^^^^^^^^^^
+   |    ^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
diff --git a/src/test/ui/lint/unused/must_use-trait.stderr b/src/test/ui/lint/unused/must_use-trait.stderr
index a42eb8841789d..2f54964848359 100644
--- a/src/test/ui/lint/unused/must_use-trait.stderr
+++ b/src/test/ui/lint/unused/must_use-trait.stderr
@@ -2,7 +2,7 @@ error: unused implementer of `Critical` that must be used
   --> $DIR/must_use-trait.rs:33:5
    |
 LL |     get_critical();
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/must_use-trait.rs:1:9
@@ -14,13 +14,13 @@ error: unused boxed `Critical` trait object that must be used
   --> $DIR/must_use-trait.rs:34:5
    |
 LL |     get_boxed_critical();
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: unused boxed boxed `Critical` trait object that must be used
   --> $DIR/must_use-trait.rs:35:5
    |
 LL |     get_nested_boxed_critical();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unused boxed `Critical` trait object in tuple element 1 that must be used
   --> $DIR/must_use-trait.rs:37:5
diff --git a/src/test/ui/lint/unused/must_use-unit.stderr b/src/test/ui/lint/unused/must_use-unit.stderr
index 7f25a19350862..9fcbc5074ea80 100644
--- a/src/test/ui/lint/unused/must_use-unit.stderr
+++ b/src/test/ui/lint/unused/must_use-unit.stderr
@@ -2,7 +2,7 @@ error: unused return value of `foo` that must be used
   --> $DIR/must_use-unit.rs:13:5
    |
 LL |     foo();
-   |     ^^^^^^
+   |     ^^^^^
    |
 note: the lint level is defined here
   --> $DIR/must_use-unit.rs:2:9
@@ -14,7 +14,7 @@ error: unused return value of `bar` that must be used
   --> $DIR/must_use-unit.rs:15:5
    |
 LL |     bar();
-   |     ^^^^^^
+   |     ^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lint/unused/unused-async.rs b/src/test/ui/lint/unused/unused-async.rs
index 7d17af1157379..4be93aa155ad9 100644
--- a/src/test/ui/lint/unused/unused-async.rs
+++ b/src/test/ui/lint/unused/unused-async.rs
@@ -1,24 +1,43 @@
 // edition:2018
-// run-pass
-#![allow(dead_code)]
+#![deny(unused_must_use)]
+
 
 #[must_use]
-//~^ WARNING `must_use`
-async fn test() -> i32 {
+async fn foo() -> i32 {
     1
 }
 
+#[must_use]
+fn bar() -> impl std::future::Future<Output=i32> {
+    async {
+        42
+    }
+}
+
+async fn baz() -> i32 {
+    0
+}
 
 struct Wowee {}
 
 impl Wowee {
     #[must_use]
-    //~^ WARNING `must_use`
     async fn test_method() -> i32 {
         1
     }
 }
 
+async fn test() {
+    foo(); //~ ERROR unused return value of `foo` that must be used
+    //~^ ERROR unused implementer of `Future` that must be used
+    foo().await; //~ ERROR unused output of future returned by `foo` that must be used
+    bar(); //~ ERROR unused return value of `bar` that must be used
+    //~^ ERROR unused implementer of `Future` that must be used
+    bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+    baz(); //~ ERROR unused implementer of `Future` that must be used
+    baz().await; // ok
+}
+
 /* FIXME(guswynn) update this test when async-fn-in-traits works
 trait Doer {
     #[must_use]
diff --git a/src/test/ui/lint/unused/unused-async.stderr b/src/test/ui/lint/unused/unused-async.stderr
index 6bbc9e2bf0088..4bcb26dc16586 100644
--- a/src/test/ui/lint/unused/unused-async.stderr
+++ b/src/test/ui/lint/unused/unused-async.stderr
@@ -1,26 +1,55 @@
-warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
-  --> $DIR/unused-async.rs:5:1
-   |
-LL |   #[must_use]
-   |   ^^^^^^^^^^^
-LL |
-LL | / async fn test() -> i32 {
-LL | |     1
-LL | | }
-   | |_- this attribute does nothing, the `Future`s returned by async functions are already `must_use`
-   |
-   = note: `#[warn(unused_attributes)]` on by default
-
-warning: `must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
-  --> $DIR/unused-async.rs:15:5
-   |
-LL |       #[must_use]
-   |       ^^^^^^^^^^^
-LL |
-LL | /     async fn test_method() -> i32 {
-LL | |         1
-LL | |     }
-   | |_____- this attribute does nothing, the `Future`s returned by async functions are already `must_use`
-
-warning: 2 warnings emitted
+error: unused implementer of `Future` that must be used
+  --> $DIR/unused-async.rs:31:5
+   |
+LL |     foo();
+   |     ^^^^^
+   |
+   = note: futures do nothing unless you `.await` or poll them
+note: the lint level is defined here
+  --> $DIR/unused-async.rs:2:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: unused return value of `foo` that must be used
+  --> $DIR/unused-async.rs:31:5
+   |
+LL |     foo();
+   |     ^^^^^
+
+error: unused output of future returned by `foo` that must be used
+  --> $DIR/unused-async.rs:33:5
+   |
+LL |     foo().await;
+   |     ^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+  --> $DIR/unused-async.rs:34:5
+   |
+LL |     bar();
+   |     ^^^^^
+   |
+   = note: futures do nothing unless you `.await` or poll them
+
+error: unused return value of `bar` that must be used
+  --> $DIR/unused-async.rs:34:5
+   |
+LL |     bar();
+   |     ^^^^^
+
+error: unused output of future returned by `bar` that must be used
+  --> $DIR/unused-async.rs:36:5
+   |
+LL |     bar().await;
+   |     ^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+  --> $DIR/unused-async.rs:37:5
+   |
+LL |     baz();
+   |     ^^^^^
+   |
+   = note: futures do nothing unless you `.await` or poll them
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/lint/unused/unused-closure.stderr b/src/test/ui/lint/unused/unused-closure.stderr
index 4362abd2037ff..c3a82402e0a2e 100644
--- a/src/test/ui/lint/unused/unused-closure.stderr
+++ b/src/test/ui/lint/unused/unused-closure.stderr
@@ -4,7 +4,7 @@ error: unused closure that must be used
 LL | /     || {
 LL | |         println!("Hello!");
 LL | |     };
-   | |______^
+   | |_____^
    |
    = note: closures are lazy and do nothing unless called
 note: the lint level is defined here
@@ -17,7 +17,7 @@ error: unused implementer of `Future` that must be used
   --> $DIR/unused-closure.rs:13:5
    |
 LL |     async {};
-   |     ^^^^^^^^^
+   |     ^^^^^^^^
    |
    = note: futures do nothing unless you `.await` or poll them
 
@@ -25,7 +25,7 @@ error: unused closure that must be used
   --> $DIR/unused-closure.rs:14:5
    |
 LL |     || async {};
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -33,7 +33,7 @@ error: unused closure that must be used
   --> $DIR/unused-closure.rs:15:5
    |
 LL |     async || {};
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -41,7 +41,7 @@ error: unused array of boxed arrays of closures that must be used
   --> $DIR/unused-closure.rs:18:5
    |
 LL |     [Box::new([|| {}; 10]); 1];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -49,7 +49,7 @@ error: unused closure that must be used
   --> $DIR/unused-closure.rs:20:5
    |
 LL |     vec![|| "a"].pop().unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
@@ -57,7 +57,7 @@ error: unused closure that must be used
   --> $DIR/unused-closure.rs:23:9
    |
 LL |         || true;
-   |         ^^^^^^^^
+   |         ^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
 
diff --git a/src/test/ui/lint/unused/unused-result.stderr b/src/test/ui/lint/unused/unused-result.stderr
index 087e06341cdde..4e1ba1fd9595f 100644
--- a/src/test/ui/lint/unused/unused-result.stderr
+++ b/src/test/ui/lint/unused/unused-result.stderr
@@ -2,7 +2,7 @@ error: unused `MustUse` that must be used
   --> $DIR/unused-result.rs:21:5
    |
 LL |     foo::<MustUse>();
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-result.rs:2:25
@@ -14,7 +14,7 @@ error: unused `MustUseMsg` that must be used
   --> $DIR/unused-result.rs:22:5
    |
 LL |     foo::<MustUseMsg>();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: some message
 
@@ -34,13 +34,13 @@ error: unused `MustUse` that must be used
   --> $DIR/unused-result.rs:35:5
    |
 LL |     foo::<MustUse>();
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
 
 error: unused `MustUseMsg` that must be used
   --> $DIR/unused-result.rs:36:5
    |
 LL |     foo::<MustUseMsg>();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: some message
 
diff --git a/src/test/ui/lint/unused/unused-supertrait.stderr b/src/test/ui/lint/unused/unused-supertrait.stderr
index d2f8c00784817..cb45add9c2b1b 100644
--- a/src/test/ui/lint/unused/unused-supertrait.stderr
+++ b/src/test/ui/lint/unused/unused-supertrait.stderr
@@ -2,7 +2,7 @@ error: unused implementer of `Iterator` that must be used
   --> $DIR/unused-supertrait.rs:9:5
    |
 LL |     it();
-   |     ^^^^^
+   |     ^^^^
    |
    = note: iterators are lazy and do nothing unless consumed
 note: the lint level is defined here
diff --git a/src/test/ui/lint/unused/unused_attributes-must_use.stderr b/src/test/ui/lint/unused/unused_attributes-must_use.stderr
index ce959ddbc4697..0f699429e0243 100644
--- a/src/test/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/src/test/ui/lint/unused/unused_attributes-must_use.stderr
@@ -139,7 +139,7 @@ error: unused `X` that must be used
   --> $DIR/unused_attributes-must_use.rs:103:5
    |
 LL |     X;
-   |     ^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/unused_attributes-must_use.rs:2:28
@@ -151,37 +151,37 @@ error: unused `Y` that must be used
   --> $DIR/unused_attributes-must_use.rs:104:5
    |
 LL |     Y::Z;
-   |     ^^^^^
+   |     ^^^^
 
 error: unused `U` that must be used
   --> $DIR/unused_attributes-must_use.rs:105:5
    |
 LL |     U { unit: () };
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^
 
 error: unused return value of `U::method` that must be used
   --> $DIR/unused_attributes-must_use.rs:106:5
    |
 LL |     U::method();
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^
 
 error: unused return value of `foo` that must be used
   --> $DIR/unused_attributes-must_use.rs:107:5
    |
 LL |     foo();
-   |     ^^^^^^
+   |     ^^^^^
 
 error: unused return value of `foreign_foo` that must be used
   --> $DIR/unused_attributes-must_use.rs:110:9
    |
 LL |         foreign_foo();
-   |         ^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^
 
 error: unused return value of `Use::get_four` that must be used
   --> $DIR/unused_attributes-must_use.rs:118:5
    |
 LL |     ().get_four();
-   |     ^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to 28 previous errors
 
diff --git a/src/test/ui/nll/issue-48623-generator.stderr b/src/test/ui/nll/issue-48623-generator.stderr
index 1b35165db45dc..bfdfca2100406 100644
--- a/src/test/ui/nll/issue-48623-generator.stderr
+++ b/src/test/ui/nll/issue-48623-generator.stderr
@@ -2,7 +2,7 @@ warning: unused generator that must be used
   --> $DIR/issue-48623-generator.rs:15:5
    |
 LL |     move || { d; yield; &mut *r };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: generators are lazy and do nothing unless resumed
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/src/test/ui/resolve/issue-103474.rs b/src/test/ui/resolve/issue-103474.rs
new file mode 100644
index 0000000000000..14f2259e1d4e8
--- /dev/null
+++ b/src/test/ui/resolve/issue-103474.rs
@@ -0,0 +1,28 @@
+struct S {}
+impl S {
+    fn first(&self) {}
+
+    fn second(&self) {
+        first()
+        //~^ ERROR cannot find function `first` in this scope
+    }
+
+    fn third(&self) {
+        no_method_err()
+        //~^ ERROR cannot find function `no_method_err` in this scope
+    }
+}
+
+// https://github.com/rust-lang/rust/pull/103531#discussion_r1004728080
+struct Foo {
+    i: i32,
+}
+
+impl Foo {
+    fn needs_self() {
+        this.i
+        //~^ ERROR cannot find value `this` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-103474.stderr b/src/test/ui/resolve/issue-103474.stderr
new file mode 100644
index 0000000000000..415d231552a03
--- /dev/null
+++ b/src/test/ui/resolve/issue-103474.stderr
@@ -0,0 +1,35 @@
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-103474.rs:23:9
+   |
+LL |         this.i
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.i
+   |         ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn needs_self(&self) {
+   |                   +++++
+
+error[E0425]: cannot find function `first` in this scope
+  --> $DIR/issue-103474.rs:6:9
+   |
+LL |         first()
+   |         ^^^^^ not found in this scope
+   |
+help: consider using the associated function
+   |
+LL |         self.first()
+   |         +++++
+
+error[E0425]: cannot find function `no_method_err` in this scope
+  --> $DIR/issue-103474.rs:11:9
+   |
+LL |         no_method_err()
+   |         ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
index e7c53ff44e6fe..36f3da7c95537 100644
--- a/src/test/ui/resolve/issue-2356.stderr
+++ b/src/test/ui/resolve/issue-2356.stderr
@@ -85,7 +85,7 @@ LL |         static_method();
 help: consider using the associated function
    |
 LL |         Self::static_method();
-   |         ~~~~~~~~~~~~~~~~~~~
+   |         ++++++
 
 error[E0425]: cannot find function `purr` in this scope
   --> $DIR/issue-2356.rs:54:9
@@ -114,7 +114,7 @@ LL |     grow_older();
 help: consider using the associated function
    |
 LL |     Self::grow_older();
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++
 
 error[E0425]: cannot find function `shave` in this scope
   --> $DIR/issue-2356.rs:74:5
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 6ee32314607ad..9577952119adb 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -1,12 +1,10 @@
 error[E0277]: the trait bound `f32: Termination` is not satisfied
-  --> $DIR/termination-trait-test-wrong-type.rs:6:1
+  --> $DIR/termination-trait-test-wrong-type.rs:6:31
    |
-LL |   #[test]
-   |   ------- in this procedural macro expansion
-LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
-LL | |     "0".parse()
-LL | | }
-   | |_^ the trait `Termination` is not implemented for `f32`
+LL | #[test]
+   | ------- in this procedural macro expansion
+LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
    |
    = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
diff --git a/src/test/ui/sanitize/memory-passing.rs b/src/test/ui/sanitize/memory-passing.rs
new file mode 100644
index 0000000000000..6d9b70ad6b1c2
--- /dev/null
+++ b/src/test/ui/sanitize/memory-passing.rs
@@ -0,0 +1,32 @@
+// needs-sanitizer-support
+// needs-sanitizer-memory
+//
+// revisions: unoptimized optimized
+//
+// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins
+//
+// run-pass
+//
+// This test case intentionally limits the usage of the std,
+// since it will be linked with an uninstrumented version of it.
+
+#![feature(core_intrinsics)]
+#![feature(start)]
+#![allow(invalid_value)]
+
+use std::hint::black_box;
+
+fn calling_black_box_on_zst_ok() {
+    // It's OK to call black_box on a value of a zero-sized type, even if its
+    // underlying the memory location is uninitialized. For non-zero-sized types,
+    // this would be an MSAN error.
+    let zst = ();
+    black_box(zst);
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    calling_black_box_on_zst_ok();
+    0
+}
diff --git a/src/test/ui/self/class-missing-self.stderr b/src/test/ui/self/class-missing-self.stderr
index d501200d73cec..063c3f013c539 100644
--- a/src/test/ui/self/class-missing-self.stderr
+++ b/src/test/ui/self/class-missing-self.stderr
@@ -10,6 +10,10 @@ error[E0425]: cannot find function `sleep` in this scope
 LL |       sleep();
    |       ^^^^^ not found in this scope
    |
+help: consider using the associated function
+   |
+LL |       self.sleep();
+   |       +++++
 help: consider importing this function
    |
 LL | use std::thread::sleep;
diff --git a/src/test/ui/suggestions/assoc_fn_without_self.stderr b/src/test/ui/suggestions/assoc_fn_without_self.stderr
index 88920b852905b..febdd67338c99 100644
--- a/src/test/ui/suggestions/assoc_fn_without_self.stderr
+++ b/src/test/ui/suggestions/assoc_fn_without_self.stderr
@@ -7,13 +7,18 @@ LL |         foo();
 help: consider using the associated function
    |
 LL |         Self::foo();
-   |         ~~~~~~~~~
+   |         ++++++
 
 error[E0425]: cannot find function `bar` in this scope
   --> $DIR/assoc_fn_without_self.rs:17:9
    |
 LL |         bar();
    |         ^^^ not found in this scope
+   |
+help: consider using the associated function
+   |
+LL |         self.bar();
+   |         +++++
 
 error[E0425]: cannot find function `baz` in this scope
   --> $DIR/assoc_fn_without_self.rs:18:9
@@ -24,7 +29,7 @@ LL |         baz(2, 3);
 help: consider using the associated function
    |
 LL |         Self::baz(2, 3);
-   |         ~~~~~~~~~
+   |         ++++++
 
 error[E0425]: cannot find function `foo` in this scope
   --> $DIR/assoc_fn_without_self.rs:14:13
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index ec992da681219..8e7c39e72b68b 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -39,6 +39,8 @@ macro_rules! t {
 }
 
 static TEST: AtomicUsize = AtomicUsize::new(0);
+const RETRY_INTERVAL: u64 = 1;
+const NUMBER_OF_RETRIES: usize = 5;
 
 #[derive(Copy, Clone)]
 struct Config {
@@ -115,7 +117,7 @@ fn main() {
     let config = Config::parse_args();
     println!("starting test server");
 
-    let listener = t!(TcpListener::bind(config.bind));
+    let listener = bind_socket(config.bind);
     let (work, tmp): (PathBuf, PathBuf) = if cfg!(target_os = "android") {
         ("/data/local/tmp/work".into(), "/data/local/tmp/work/tmp".into())
     } else {
@@ -159,6 +161,16 @@ fn main() {
     }
 }
 
+fn bind_socket(addr: SocketAddr) -> TcpListener {
+    for _ in 0..(NUMBER_OF_RETRIES - 1) {
+        if let Ok(x) = TcpListener::bind(addr) {
+            return x;
+        }
+        std::thread::sleep(std::time::Duration::from_secs(RETRY_INTERVAL));
+    }
+    TcpListener::bind(addr).unwrap()
+}
+
 fn handle_push(socket: TcpStream, work: &Path, config: Config) {
     let mut reader = BufReader::new(socket);
     let dst = recv(&work, &mut reader);