about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-06-24 10:22:30 +0000
committerbors <bors@rust-lang.org>2025-06-24 10:22:30 +0000
commit36b21637e93b038453924d3c66821089e71d8baa (patch)
treee5abef64f88d9244a0394e45b105762d68ed275f
parente4b9d0141fdd210fcceebd2b67f7be113401c461 (diff)
parent7b864ac1905f0b118d2e4ca1beeede86ac91e5a1 (diff)
downloadrust-36b21637e93b038453924d3c66821089e71d8baa.tar.gz
rust-36b21637e93b038453924d3c66821089e71d8baa.zip
Auto merge of #142956 - GuillaumeGomez:rollup-867246h, r=GuillaumeGomez
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#140005 (Set MSG_NOSIGNAL for UnixStream)
 - rust-lang/rust#140622 (compiletest: Improve diagnostics for line annotation mismatches)
 - rust-lang/rust#142354 (Fixes firefox copy paste issue)
 - rust-lang/rust#142695 (Port `#[rustc_skip_during_method_dispatch]` to the new attribute system)
 - rust-lang/rust#142779 (Add note about `str::split` handling of no matches.)
 - rust-lang/rust#142894 (phantom_variance_markers: fix identifier usage in macro)
 - rust-lang/rust#142928 (Fix hang in --print=file-names in bootstrap)
 - rust-lang/rust#142932 (rustdoc-json: Keep empty generic args if parenthesized)
 - rust-lang/rust#142933 (Simplify root goal API of solver a bit)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs14
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/semantics.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/stability.rs9
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs54
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs22
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs47
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs7
-rw-r--r--compiler/rustc_passes/src/check_attr.rs15
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs24
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs18
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs20
-rw-r--r--library/core/src/marker/variance.rs2
-rw-r--r--library/core/src/str/mod.rs6
-rw-r--r--library/std/src/net/tcp.rs6
-rw-r--r--library/std/src/os/unix/net/stream.rs23
-rw-r--r--library/std/src/sys/net/connection/socket/unix.rs8
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs1
-rw-r--r--src/bootstrap/src/utils/exec.rs5
-rw-r--r--src/librustdoc/html/static/js/main.js30
-rw-r--r--src/librustdoc/json/conversions.rs29
-rw-r--r--src/tools/compiletest/src/errors.rs46
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/json.rs40
-rw-r--r--src/tools/compiletest/src/runtest.rs147
-rw-r--r--tests/incremental/issue-61323.rs2
-rw-r--r--tests/rustdoc-json/generic-args.rs3
-rw-r--r--tests/ui/argument-suggestions/issue-100478.rs4
-rw-r--r--tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed2
-rw-r--r--tests/ui/async-await/incorrect-move-async-order-issue-79694.rs2
-rw-r--r--tests/ui/attributes/rustc_skip_during_method_dispatch.rs38
-rw-r--r--tests/ui/attributes/rustc_skip_during_method_dispatch.stderr76
-rw-r--r--tests/ui/compiletest-self-test/line-annotation-mismatches.rs42
-rw-r--r--tests/ui/compiletest-self-test/line-annotation-mismatches.stderr61
-rw-r--r--tests/ui/feature-gates/feature-gate-cfi_encoding.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs2
-rw-r--r--tests/ui/impl-header-lifetime-elision/assoc-type.rs2
-rw-r--r--tests/ui/imports/issue-28134.rs2
-rw-r--r--tests/ui/inference/hint-closure-signature-119266.rs2
-rw-r--r--tests/ui/integral-indexing.rs16
-rw-r--r--tests/ui/issues/issue-92741.rs6
-rw-r--r--tests/ui/lifetimes/no_lending_iterators.rs6
-rw-r--r--tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs8
-rw-r--r--tests/ui/sanitizer/cfi/invalid-attr-encoding.rs2
-rw-r--r--tests/ui/suggestions/issue-105645.rs2
-rw-r--r--tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs2
-rw-r--r--tests/ui/type/option-ref-advice.rs4
-rw-r--r--tests/ui/typeck/issue-100246.rs2
-rw-r--r--tests/ui/typeck/issue-89275.rs2
56 files changed, 681 insertions, 236 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index 9227b81f12f..ae3a1a41387 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -259,6 +259,9 @@ pub enum AttributeKind {
     /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
     Repr(ThinVec<(ReprAttr, Span)>),
 
+    /// Represents `#[rustc_skip_during_method_dispatch]`.
+    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
+
     /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
     Stability {
         stability: Stability,
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 24c40c301fe..0fa69c40154 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -50,8 +50,8 @@ impl<S: Stage> SingleAttributeParser<S> for ColdParser {
     const TEMPLATE: AttributeTemplate = template!(Word);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
-        if !args.no_args() {
-            cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
             return None;
         }
 
@@ -67,8 +67,8 @@ pub(crate) struct NakedParser {
 impl<S: Stage> AttributeParser<S> for NakedParser {
     const ATTRIBUTES: AcceptMapping<Self, S> =
         &[(&[sym::naked], template!(Word), |this, cx, args| {
-            if !args.no_args() {
-                cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
+            if let Err(span) = args.no_args() {
+                cx.expected_no_args(span);
                 return;
             }
 
@@ -175,10 +175,10 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser {
     const TEMPLATE: AttributeTemplate = template!(Word);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
-        if !args.no_args() {
-            cx.expected_no_args(args.span().unwrap_or(cx.attr_span));
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
             return None;
-        };
+        }
 
         Some(AttributeKind::NoMangle(cx.attr_span))
     }
diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
index 4cfd9a82ce8..1c8fc5079da 100644
--- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
@@ -14,8 +14,10 @@ impl<S: Stage> SingleAttributeParser<S> for AsPtrParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(Word);
 
-    fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
-        // FIXME: check that there's no args (this is currently checked elsewhere)
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
+        }
         Some(AttributeKind::AsPtr(cx.attr_span))
     }
 }
@@ -27,8 +29,10 @@ impl<S: Stage> SingleAttributeParser<S> for PubTransparentParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(Word);
 
-    fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
-        // FIXME: check that there's no args (this is currently checked elsewhere)
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
+        }
         Some(AttributeKind::PubTransparent(cx.attr_span))
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 738d8735b69..ac7e90fd902 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -36,6 +36,7 @@ pub(crate) mod must_use;
 pub(crate) mod repr;
 pub(crate) mod semantics;
 pub(crate) mod stability;
+pub(crate) mod traits;
 pub(crate) mod transparency;
 pub(crate) mod util;
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs
index 071574a5612..54f50445fbd 100644
--- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs
@@ -13,7 +13,10 @@ impl<S: Stage> SingleAttributeParser<S> for MayDangleParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const TEMPLATE: AttributeTemplate = template!(Word);
 
-    fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
+        }
         Some(AttributeKind::MayDangle(cx.attr_span))
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 6871ff4ec9f..37104855623 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -139,7 +139,10 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
     const TEMPLATE: AttributeTemplate = template!(Word);
 
-    fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        if let Err(span) = args.no_args() {
+            cx.expected_no_args(span);
+        }
         Some(AttributeKind::ConstStabilityIndirect)
     }
 }
@@ -361,8 +364,8 @@ pub(crate) fn parse_unstability<S: Stage>(
                 };
             }
             Some(sym::soft) => {
-                if !param.args().no_args() {
-                    cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() });
+                if let Err(span) = args.no_args() {
+                    cx.emit_err(session_diagnostics::SoftNoArgs { span });
                 }
                 is_soft = true;
             }
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
new file mode 100644
index 00000000000..83a98c53c7f
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -0,0 +1,54 @@
+use core::mem;
+
+use rustc_attr_data_structures::AttributeKind;
+use rustc_feature::{AttributeTemplate, template};
+use rustc_span::{Symbol, sym};
+
+use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
+use crate::context::{AcceptContext, Stage};
+use crate::parser::ArgParser;
+
+pub(crate) struct SkipDuringMethodDispatchParser;
+
+impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
+    const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+
+    const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice");
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let mut array = false;
+        let mut boxed_slice = false;
+        let Some(args) = args.list() else {
+            cx.expected_list(cx.attr_span);
+            return None;
+        };
+        if args.is_empty() {
+            cx.expected_at_least_one_argument(args.span);
+            return None;
+        }
+        for arg in args.mixed() {
+            let Some(arg) = arg.meta_item() else {
+                cx.unexpected_literal(arg.span());
+                continue;
+            };
+            if let Err(span) = arg.args().no_args() {
+                cx.expected_no_args(span);
+            }
+            let path = arg.path();
+            let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
+                Some(key @ sym::array) => (key, &mut array),
+                Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
+                _ => {
+                    cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]);
+                    continue;
+                }
+            };
+            if mem::replace(skip, true) {
+                cx.duplicate_key(arg.span(), key);
+            }
+        }
+        Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 457e073c488..43b2d07dbe1 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -26,6 +26,7 @@ use crate::attributes::semantics::MayDangleParser;
 use crate::attributes::stability::{
     BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
 };
+use crate::attributes::traits::SkipDuringMethodDispatchParser;
 use crate::attributes::transparency::TransparencyParser;
 use crate::attributes::{AttributeParser as _, Combine, Single};
 use crate::parser::{ArgParser, MetaItemParser, PathParser};
@@ -119,6 +120,7 @@ attribute_parsers!(
         Single<OptimizeParser>,
         Single<PubTransparentParser>,
         Single<RustcForceInlineParser>,
+        Single<SkipDuringMethodDispatchParser>,
         Single<TransparencyParser>,
         // tidy-alphabetical-end
     ];
@@ -325,6 +327,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
         })
     }
 
+    pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
+        self.emit_err(AttributeParseError {
+            span,
+            attr_span: self.attr_span,
+            template: self.template.clone(),
+            attribute: self.attr_path.clone(),
+            reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
+        })
+    }
+
     pub(crate) fn expected_specific_argument(
         &self,
         span: Span,
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index e02dc098127..aecaae947c9 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -169,9 +169,15 @@ impl<'a> ArgParser<'a> {
         }
     }
 
-    /// Asserts that there are no arguments
-    pub fn no_args(&self) -> bool {
-        matches!(self, Self::NoArgs)
+    /// Assert that there were no args.
+    /// If there were, get a span to the arguments
+    /// (to pass to [`AcceptContext::expected_no_args`](crate::context::AcceptContext::expected_no_args)).
+    pub fn no_args(&self) -> Result<(), Span> {
+        match self {
+            Self::NoArgs => Ok(()),
+            Self::List(args) => Err(args.span),
+            Self::NameValue(args) => Err(args.eq_span.to(args.value_span)),
+        }
     }
 }
 
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 808e452799d..263b323e3eb 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -496,6 +496,7 @@ pub(crate) struct NakedFunctionIncompatibleAttribute {
 pub(crate) enum AttributeParseErrorReason {
     ExpectedNoArgs,
     ExpectedStringLiteral { byte_string: Option<Span> },
+    ExpectedAtLeastOneArgument,
     ExpectedSingleArgument,
     ExpectedList,
     UnexpectedLiteral,
@@ -539,6 +540,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
                 diag.span_label(self.span, "expected a single argument here");
                 diag.code(E0805);
             }
+            AttributeParseErrorReason::ExpectedAtLeastOneArgument => {
+                diag.span_label(self.span, "expected at least 1 argument here");
+            }
             AttributeParseErrorReason::ExpectedList => {
                 diag.span_label(self.span, "expected this to be a list");
             }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 280b33f0723..3540c9b4bf0 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1083,7 +1083,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "the `#[rustc_main]` attribute is used internally to specify test entry point function",
     ),
     rustc_attr!(
-        rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), WarnFollowing,
+        rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing,
         EncodeCrossCrate::No,
         "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
         from method dispatch when the receiver is of the following type, for compatibility in \
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 176d955bf03..c967e87bfd8 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -21,6 +21,7 @@ use std::ops::Bound;
 
 use rustc_abi::ExternAbi;
 use rustc_ast::Recovered;
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{
@@ -1151,22 +1152,11 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
     let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
     let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
 
-    // FIXME: We could probably do way better attribute validation here.
-    let mut skip_array_during_method_dispatch = false;
-    let mut skip_boxed_slice_during_method_dispatch = false;
-    for attr in tcx.get_attrs(def_id, sym::rustc_skip_during_method_dispatch) {
-        if let Some(lst) = attr.meta_item_list() {
-            for item in lst {
-                if let Some(ident) = item.ident() {
-                    match ident.as_str() {
-                        "array" => skip_array_during_method_dispatch = true,
-                        "boxed_slice" => skip_boxed_slice_during_method_dispatch = true,
-                        _ => (),
-                    }
-                }
-            }
-        }
-    }
+    let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
+        tcx.get_all_attrs(def_id),
+        AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
+    )
+    .unwrap_or([false; 2]);
 
     let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
         ty::trait_def::TraitSpecializationKind::Marker
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 00fd3ba8046..780feb9b827 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -147,13 +147,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
     fn evaluate_root_goal(
         &self,
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
-        generate_proof_tree: GenerateProofTree,
         span: <Self::Interner as Interner>::Span,
         stalled_on: Option<GoalStalledOn<Self::Interner>>,
-    ) -> (
-        Result<GoalEvaluation<Self::Interner>, NoSolution>,
-        Option<inspect::GoalEvaluation<Self::Interner>>,
-    );
+    ) -> Result<GoalEvaluation<Self::Interner>, NoSolution>;
 
     /// Check whether evaluating `goal` with a depth of `root_depth` may
     /// succeed. This only returns `false` if the goal is guaranteed to
@@ -170,17 +166,16 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
 
     // FIXME: This is only exposed because we need to use it in `analyse.rs`
     // which is not yet uplifted. Once that's done, we should remove this.
-    fn evaluate_root_goal_raw(
+    fn evaluate_root_goal_for_proof_tree(
         &self,
         goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
-        generate_proof_tree: GenerateProofTree,
-        stalled_on: Option<GoalStalledOn<Self::Interner>>,
+        span: <Self::Interner as Interner>::Span,
     ) -> (
         Result<
             (NestedNormalizationGoals<Self::Interner>, GoalEvaluation<Self::Interner>),
             NoSolution,
         >,
-        Option<inspect::GoalEvaluation<Self::Interner>>,
+        inspect::GoalEvaluation<Self::Interner>,
     );
 }
 
@@ -193,13 +188,17 @@ where
     fn evaluate_root_goal(
         &self,
         goal: Goal<I, I::Predicate>,
-        generate_proof_tree: GenerateProofTree,
         span: I::Span,
         stalled_on: Option<GoalStalledOn<I>>,
-    ) -> (Result<GoalEvaluation<I>, NoSolution>, Option<inspect::GoalEvaluation<I>>) {
-        EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
-            ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
-        })
+    ) -> Result<GoalEvaluation<I>, NoSolution> {
+        EvalCtxt::enter_root(
+            self,
+            self.cx().recursion_limit(),
+            GenerateProofTree::No,
+            span,
+            |ecx| ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on),
+        )
+        .0
     }
 
     fn root_goal_may_hold_with_depth(
@@ -217,24 +216,22 @@ where
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn evaluate_root_goal_raw(
+    fn evaluate_root_goal_for_proof_tree(
         &self,
         goal: Goal<I, I::Predicate>,
-        generate_proof_tree: GenerateProofTree,
-        stalled_on: Option<GoalStalledOn<I>>,
+        span: I::Span,
     ) -> (
         Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution>,
-        Option<inspect::GoalEvaluation<I>>,
+        inspect::GoalEvaluation<I>,
     ) {
-        EvalCtxt::enter_root(
+        let (result, proof_tree) = EvalCtxt::enter_root(
             self,
             self.cx().recursion_limit(),
-            generate_proof_tree,
-            I::Span::dummy(),
-            |ecx| {
-                ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on)
-            },
-        )
+            GenerateProofTree::Yes,
+            span,
+            |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, None),
+        );
+        (result, proof_tree.unwrap())
     }
 }
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 8e6442353c3..47e29923ee5 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -286,13 +286,20 @@ fn emit_malformed_attribute(
     if matches!(
         name,
         sym::inline
+            | sym::may_dangle
+            | sym::rustc_as_ptr
+            | sym::rustc_pub_transparent
+            | sym::rustc_const_stable_indirect
             | sym::rustc_force_inline
             | sym::rustc_confusables
+            | sym::rustc_skip_during_method_dispatch
             | sym::repr
             | sym::align
             | sym::deprecated
             | sym::optimize
             | sym::cold
+            | sym::naked
+            | sym::no_mangle
             | sym::must_use
     ) {
         return;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c2a58b4cd7d..25b84179443 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -118,6 +118,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         for attr in attrs {
             let mut style = None;
             match attr {
+                Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch {
+                    span: attr_span,
+                    ..
+                }) => {
+                    self.check_must_be_applied_to_trait(*attr_span, span, target);
+                }
                 Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
                     self.check_confusables(*first_span, target);
                 }
@@ -250,7 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         | [sym::rustc_must_implement_one_of, ..]
                         | [sym::rustc_deny_explicit_impl, ..]
                         | [sym::rustc_do_not_implement_via_object, ..]
-                        | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
+                        | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
                         [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
                         [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
                         [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
@@ -1805,14 +1811,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Checks if the attribute is applied to a trait.
-    fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) {
+    fn check_must_be_applied_to_trait(&self, attr_span: Span, defn_span: Span, target: Target) {
         match target {
             Target::Trait => {}
             _ => {
-                self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
-                    attr_span: attr.span(),
-                    defn_span: span,
-                });
+                self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span });
             }
         }
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 684b1781b44..5861ae4a372 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -577,6 +577,7 @@ symbols! {
         box_new,
         box_patterns,
         box_syntax,
+        boxed_slice,
         bpf_target_feature,
         braced_empty_structs,
         branch,
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index ed99c678a4d..d56042a5ca2 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::{
 };
 use rustc_next_trait_solver::delegate::SolverDelegate as _;
 use rustc_next_trait_solver::solve::{
-    GenerateProofTree, GoalEvaluation, GoalStalledOn, HasChanged, SolverDelegateEvalExt as _,
+    GoalEvaluation, GoalStalledOn, HasChanged, SolverDelegateEvalExt as _,
 };
 use rustc_span::Span;
 use thin_vec::ThinVec;
@@ -106,14 +106,11 @@ impl<'tcx> ObligationStorage<'tcx> {
             self.overflowed.extend(
                 ExtractIf::new(&mut self.pending, |(o, stalled_on)| {
                     let goal = o.as_goal();
-                    let result = <&SolverDelegate<'tcx>>::from(infcx)
-                        .evaluate_root_goal(
-                            goal,
-                            GenerateProofTree::No,
-                            o.cause.span,
-                            stalled_on.take(),
-                        )
-                        .0;
+                    let result = <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal(
+                        goal,
+                        o.cause.span,
+                        stalled_on.take(),
+                    );
                     matches!(result, Ok(GoalEvaluation { has_changed: HasChanged::Yes, .. }))
                 })
                 .map(|(o, _)| o),
@@ -207,14 +204,7 @@ where
                     continue;
                 }
 
-                let result = delegate
-                    .evaluate_root_goal(
-                        goal,
-                        GenerateProofTree::No,
-                        obligation.cause.span,
-                        stalled_on,
-                    )
-                    .0;
+                let result = delegate.evaluate_root_goal(goal, obligation.cause.span, stalled_on);
                 self.inspect_evaluated_obligation(infcx, &obligation, &result);
                 let GoalEvaluation { certainty, has_changed, stalled_on } = match result {
                     Ok(result) => result,
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 36a8ae675c0..fe248b033bb 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -11,9 +11,7 @@ use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
-use rustc_next_trait_solver::solve::{
-    GenerateProofTree, GoalEvaluation, SolverDelegateEvalExt as _,
-};
+use rustc_next_trait_solver::solve::{GoalEvaluation, SolverDelegateEvalExt as _};
 use tracing::{instrument, trace};
 
 use crate::solve::delegate::SolverDelegate;
@@ -90,15 +88,11 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>(
     root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
     let (code, refine_obligation) = infcx.probe(|_| {
-        match <&SolverDelegate<'tcx>>::from(infcx)
-            .evaluate_root_goal(
-                root_obligation.as_goal(),
-                GenerateProofTree::No,
-                root_obligation.cause.span,
-                None,
-            )
-            .0
-        {
+        match <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal(
+            root_obligation.as_goal(),
+            root_obligation.cause.span,
+            None,
+        ) {
             Ok(GoalEvaluation { certainty: Certainty::Maybe(MaybeCause::Ambiguity), .. }) => {
                 (FulfillmentErrorCode::Ambiguity { overflow: None }, true)
             }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index b0c8fa1f217..80df0fab2d8 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::{TyCtxt, VisitorResult, try_visit};
 use rustc_middle::{bug, ty};
 use rustc_next_trait_solver::resolve::eager_resolve_vars;
 use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state};
-use rustc_next_trait_solver::solve::{GenerateProofTree, MaybeCause, SolverDelegateEvalExt as _};
+use rustc_next_trait_solver::solve::{MaybeCause, SolverDelegateEvalExt as _};
 use rustc_span::Span;
 use tracing::instrument;
 
@@ -248,9 +248,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                     // considering the constrained RHS, and pass the resulting certainty to
                     // `InspectGoal::new` so that the goal has the right result (and maintains
                     // the impression that we don't do this normalizes-to infer hack at all).
-                    let (nested, proof_tree) =
-                        infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes, None);
-                    let proof_tree = proof_tree.unwrap();
+                    let (nested, proof_tree) = infcx.evaluate_root_goal_for_proof_tree(goal, span);
                     let nested_goals_result = nested.and_then(|(nested, _)| {
                         normalizes_to_term_hack.constrain_and(
                             infcx,
@@ -284,9 +282,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 // into another candidate who ends up with different inference
                 // constraints, we get an ICE if we already applied the constraints
                 // from the chosen candidate.
-                let proof_tree = infcx
-                    .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span, None).1)
-                    .unwrap();
+                let proof_tree =
+                    infcx.probe(|_| infcx.evaluate_root_goal_for_proof_tree(goal, span).1);
                 InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
             }
         }
@@ -488,13 +485,8 @@ impl<'tcx> InferCtxt<'tcx> {
         depth: usize,
         visitor: &mut V,
     ) -> V::Result {
-        let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self).evaluate_root_goal(
-            goal,
-            GenerateProofTree::Yes,
-            visitor.span(),
-            None,
-        );
-        let proof_tree = proof_tree.unwrap();
+        let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self)
+            .evaluate_root_goal_for_proof_tree(goal, visitor.span());
         visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc))
     }
 }
diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs
index f9638fea225..55fdacb014e 100644
--- a/library/core/src/marker/variance.rs
+++ b/library/core/src/marker/variance.rs
@@ -18,7 +18,7 @@ macro_rules! phantom_type {
         pub struct $name:ident <$t:ident> ($($inner:tt)*);
     )*) => {$(
         $(#[$attr])*
-        pub struct $name<$t>($($inner)*) where T: ?Sized;
+        pub struct $name<$t>($($inner)*) where $t: ?Sized;
 
         impl<T> $name<T>
             where T: ?Sized
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 5051b2288fd..d250e1478d8 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1495,6 +1495,9 @@ impl str {
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
     ///
+    /// If there are no matches the full string slice is returned as the only
+    /// item in the iterator.
+    ///
     /// [`char`]: prim@char
     /// [pattern]: self::pattern
     ///
@@ -1526,6 +1529,9 @@ impl str {
     /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
     /// assert_eq!(v, ["lion", "tiger", "leopard"]);
     ///
+    /// let v: Vec<&str> = "AABBCC".split("DD").collect();
+    /// assert_eq!(v, ["AABBCC"]);
+    ///
     /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
     /// assert_eq!(v, ["abc", "def", "ghi"]);
     ///
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 6a951426407..10685b49319 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -53,6 +53,12 @@ use crate::time::Duration;
 ///     Ok(())
 /// } // the stream is closed here
 /// ```
+///
+/// # Platform-specific Behavior
+///
+/// On Unix, writes to the underlying socket in `SOCK_STREAM` mode are made with
+/// `MSG_NOSIGNAL` flag. This suppresses the emission of the  `SIGPIPE` signal when writing
+/// to disconnected socket. In some cases, getting a `SIGPIPE` would trigger process termination.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct TcpStream(net_imp::TcpStream);
 
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index 1bd3bab5e37..035768a6fab 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -1,3 +1,18 @@
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "linux", target_os = "android",
+        target_os = "hurd",
+        target_os = "dragonfly", target_os = "freebsd",
+        target_os = "openbsd", target_os = "netbsd",
+        target_os = "solaris", target_os = "illumos",
+        target_os = "haiku", target_os = "nto",
+        target_os = "cygwin"))] {
+        use libc::MSG_NOSIGNAL;
+    } else {
+        const MSG_NOSIGNAL: core::ffi::c_int = 0x0;
+    }
+}
+
 use super::{SocketAddr, sockaddr_un};
 #[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to};
@@ -41,6 +56,12 @@ use crate::time::Duration;
 ///     Ok(())
 /// }
 /// ```
+///
+/// # `SIGPIPE`
+///
+/// Writes to the underlying socket in `SOCK_STREAM` mode are made with `MSG_NOSIGNAL` flag.
+/// This suppresses the emission of the  `SIGPIPE` signal when writing to disconnected socket.
+/// In some cases getting a `SIGPIPE` would trigger process termination.
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixStream(pub(super) Socket);
 
@@ -633,7 +654,7 @@ impl io::Write for UnixStream {
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl<'a> io::Write for &'a UnixStream {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
+        self.0.send_with_flags(buf, MSG_NOSIGNAL)
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs
index b35d5d2aa84..b2a4961c3c5 100644
--- a/library/std/src/sys/net/connection/socket/unix.rs
+++ b/library/std/src/sys/net/connection/socket/unix.rs
@@ -281,6 +281,14 @@ impl Socket {
         self.0.duplicate().map(Socket)
     }
 
+    pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize> {
+        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
+        let ret = cvt(unsafe {
+            libc::send(self.as_raw_fd(), buf.as_ptr() as *const c_void, len, flags)
+        })?;
+        Ok(ret as usize)
+    }
+
     fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> {
         let ret = cvt(unsafe {
             libc::recv(
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 0e3c3aaee0f..99044e2a253 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -683,6 +683,7 @@ impl Builder<'_> {
                         .arg("--print=file-names")
                         .arg("--crate-type=proc-macro")
                         .arg("-")
+                        .stdin(std::process::Stdio::null())
                         .run_capture(self)
                         .stderr();
 
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index eb9802bf2e1..78b28ac1828 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -119,6 +119,11 @@ impl<'a> BootstrapCommand {
         self
     }
 
+    pub fn stdin(&mut self, stdin: std::process::Stdio) -> &mut Self {
+        self.command.stdin(stdin);
+        self
+    }
+
     #[must_use]
     pub fn delay_failure(self) -> Self {
         Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 7b1a61a3ffa..2de8f836da3 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1,6 +1,6 @@
 // Local js definitions:
 /* global addClass, getSettingValue, hasClass, updateLocalStorage */
-/* global onEachLazy, removeClass, getVar */
+/* global onEachLazy, removeClass, getVar, nonnull */
 
 "use strict";
 
@@ -2138,3 +2138,31 @@ function preLoadCss(cssUrl) {
         elem.addEventListener("click", showHideCodeExampleButtons);
     });
 }());
+
+// This section is a bugfix for firefox: when copying text with `user-select: none`, it adds
+// extra backline characters.
+//
+// Rustdoc issue: Workaround for https://github.com/rust-lang/rust/issues/141464
+// Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836
+(function() {
+    document.body.addEventListener("copy", event => {
+        let target = nonnull(event.target);
+        let isInsideCode = false;
+        while (target && target !== document.body) {
+            // @ts-expect-error
+            if (target.tagName === "CODE") {
+                isInsideCode = true;
+                break;
+            }
+            // @ts-expect-error
+            target = target.parentElement;
+        }
+        if (!isInsideCode) {
+            return;
+        }
+        const selection = document.getSelection();
+         // @ts-expect-error
+        nonnull(event.clipboardData).setData("text/plain", selection.toString());
+        event.preventDefault();
+    });
+}());
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 0778b5b56f5..f51b35097f6 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -194,22 +194,25 @@ impl FromClean<attrs::Deprecation> for Deprecation {
 }
 
 impl FromClean<clean::GenericArgs> for Option<Box<GenericArgs>> {
-    fn from_clean(args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
+    fn from_clean(generic_args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
         use clean::GenericArgs::*;
-        if args.is_empty() {
-            return None;
-        }
-        Some(Box::new(match args {
-            AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
-                args: args.into_json(renderer),
-                constraints: constraints.into_json(renderer),
-            },
-            Parenthesized { inputs, output } => GenericArgs::Parenthesized {
+        match generic_args {
+            AngleBracketed { args, constraints } => {
+                if generic_args.is_empty() {
+                    None
+                } else {
+                    Some(Box::new(GenericArgs::AngleBracketed {
+                        args: args.into_json(renderer),
+                        constraints: constraints.into_json(renderer),
+                    }))
+                }
+            }
+            Parenthesized { inputs, output } => Some(Box::new(GenericArgs::Parenthesized {
                 inputs: inputs.into_json(renderer),
                 output: output.into_json(renderer),
-            },
-            ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
-        }))
+            })),
+            ReturnTypeNotation => Some(Box::new(GenericArgs::ReturnTypeNotation)),
+        }
     }
 }
 
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index b5a2b7feac9..9fa26305f6b 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -16,6 +16,8 @@ pub enum ErrorKind {
     Suggestion,
     Warning,
     Raw,
+    /// Used for better recovery and diagnostics in compiletest.
+    Unknown,
 }
 
 impl ErrorKind {
@@ -31,21 +33,25 @@ impl ErrorKind {
 
     /// Either the canonical uppercase string, or some additional versions for compatibility.
     /// FIXME: consider keeping only the canonical versions here.
-    pub fn from_user_str(s: &str) -> ErrorKind {
-        match s {
+    fn from_user_str(s: &str) -> Option<ErrorKind> {
+        Some(match s {
             "HELP" | "help" => ErrorKind::Help,
             "ERROR" | "error" => ErrorKind::Error,
-            // `MONO_ITEM` makes annotations in `codegen-units` tests syntactically correct,
-            // but those tests never use the error kind later on.
-            "NOTE" | "note" | "MONO_ITEM" => ErrorKind::Note,
+            "NOTE" | "note" => ErrorKind::Note,
             "SUGGESTION" => ErrorKind::Suggestion,
             "WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning,
             "RAW" => ErrorKind::Raw,
-            _ => panic!(
+            _ => return None,
+        })
+    }
+
+    pub fn expect_from_user_str(s: &str) -> ErrorKind {
+        ErrorKind::from_user_str(s).unwrap_or_else(|| {
+            panic!(
                 "unexpected diagnostic kind `{s}`, expected \
-                 `ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`"
-            ),
-        }
+                 `ERROR`, `WARN`, `NOTE`, `HELP`, `SUGGESTION` or `RAW`"
+            )
+        })
     }
 }
 
@@ -58,6 +64,7 @@ impl fmt::Display for ErrorKind {
             ErrorKind::Suggestion => write!(f, "SUGGESTION"),
             ErrorKind::Warning => write!(f, "WARN"),
             ErrorKind::Raw => write!(f, "RAW"),
+            ErrorKind::Unknown => write!(f, "UNKNOWN"),
         }
     }
 }
@@ -65,6 +72,7 @@ impl fmt::Display for ErrorKind {
 #[derive(Debug)]
 pub struct Error {
     pub line_num: Option<usize>,
+    pub column_num: Option<usize>,
     /// What kind of message we expect (e.g., warning, error, suggestion).
     pub kind: ErrorKind,
     pub msg: String,
@@ -74,17 +82,6 @@ pub struct Error {
     pub require_annotation: bool,
 }
 
-impl Error {
-    pub fn render_for_expected(&self) -> String {
-        use colored::Colorize;
-        format!("{: <10}line {: >3}: {}", self.kind, self.line_num_str(), self.msg.cyan())
-    }
-
-    pub fn line_num_str(&self) -> String {
-        self.line_num.map_or("?".to_string(), |line_num| line_num.to_string())
-    }
-}
-
 /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
 /// The former is a "follow" that inherits its target from the preceding line;
 /// the latter is an "adjusts" that goes that many lines up.
@@ -168,8 +165,10 @@ fn parse_expected(
     let rest = line[tag.end()..].trim_start();
     let (kind_str, _) =
         rest.split_once(|c: char| c != '_' && !c.is_ascii_alphabetic()).unwrap_or((rest, ""));
-    let kind = ErrorKind::from_user_str(kind_str);
-    let untrimmed_msg = &rest[kind_str.len()..];
+    let (kind, untrimmed_msg) = match ErrorKind::from_user_str(kind_str) {
+        Some(kind) => (kind, &rest[kind_str.len()..]),
+        None => (ErrorKind::Unknown, rest),
+    };
     let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned();
 
     let line_num_adjust = &captures["adjust"];
@@ -182,6 +181,7 @@ fn parse_expected(
     } else {
         (false, Some(line_num - line_num_adjust.len()))
     };
+    let column_num = Some(tag.start() + 1);
 
     debug!(
         "line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}",
@@ -191,7 +191,7 @@ fn parse_expected(
         kind,
         msg
     );
-    Some((follow_prev, Error { line_num, kind, msg, require_annotation: true }))
+    Some((follow_prev, Error { line_num, column_num, kind, msg, require_annotation: true }))
 }
 
 #[cfg(test)]
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 8bee9caacc9..2b203bb309c 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -593,7 +593,7 @@ impl TestProps {
                         config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS)
                     {
                         self.dont_require_annotations
-                            .insert(ErrorKind::from_user_str(err_kind.trim()));
+                            .insert(ErrorKind::expect_from_user_str(err_kind.trim()));
                     }
                 },
             );
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 6ed2b52c66d..a8e6416e56c 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -36,9 +36,7 @@ struct UnusedExternNotification {
 struct DiagnosticSpan {
     file_name: String,
     line_start: usize,
-    line_end: usize,
     column_start: usize,
-    column_end: usize,
     is_primary: bool,
     label: Option<String>,
     suggested_replacement: Option<String>,
@@ -148,6 +146,7 @@ pub fn parse_output(file_name: &str, output: &str) -> Vec<Error> {
             Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name),
             Err(_) => errors.push(Error {
                 line_num: None,
+                column_num: None,
                 kind: ErrorKind::Raw,
                 msg: line.to_string(),
                 require_annotation: false,
@@ -193,25 +192,9 @@ fn push_actual_errors(
     // also ensure that `//~ ERROR E123` *always* works. The
     // assumption is that these multi-line error messages are on their
     // way out anyhow.
-    let with_code = |span: Option<&DiagnosticSpan>, text: &str| {
-        // FIXME(#33000) -- it'd be better to use a dedicated
-        // UI harness than to include the line/col number like
-        // this, but some current tests rely on it.
-        //
-        // Note: Do NOT include the filename. These can easily
-        // cause false matches where the expected message
-        // appears in the filename, and hence the message
-        // changes but the test still passes.
-        let span_str = match span {
-            Some(DiagnosticSpan { line_start, column_start, line_end, column_end, .. }) => {
-                format!("{line_start}:{column_start}: {line_end}:{column_end}")
-            }
-            None => format!("?:?: ?:?"),
-        };
-        match &diagnostic.code {
-            Some(code) => format!("{span_str}: {text} [{}]", code.code),
-            None => format!("{span_str}: {text}"),
-        }
+    let with_code = |text| match &diagnostic.code {
+        Some(code) => format!("{text} [{}]", code.code),
+        None => format!("{text}"),
     };
 
     // Convert multi-line messages into multiple errors.
@@ -225,8 +208,9 @@ fn push_actual_errors(
             || Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap();
         errors.push(Error {
             line_num: None,
+            column_num: None,
             kind,
-            msg: with_code(None, first_line),
+            msg: with_code(first_line),
             require_annotation: diagnostic.level != "failure-note"
                 && !RE.get_or_init(re_init).is_match(first_line),
         });
@@ -234,8 +218,9 @@ fn push_actual_errors(
         for span in primary_spans {
             errors.push(Error {
                 line_num: Some(span.line_start),
+                column_num: Some(span.column_start),
                 kind,
-                msg: with_code(Some(span), first_line),
+                msg: with_code(first_line),
                 require_annotation: true,
             });
         }
@@ -244,16 +229,18 @@ fn push_actual_errors(
         if primary_spans.is_empty() {
             errors.push(Error {
                 line_num: None,
+                column_num: None,
                 kind,
-                msg: with_code(None, next_line),
+                msg: with_code(next_line),
                 require_annotation: false,
             });
         } else {
             for span in primary_spans {
                 errors.push(Error {
                     line_num: Some(span.line_start),
+                    column_num: Some(span.column_start),
                     kind,
-                    msg: with_code(Some(span), next_line),
+                    msg: with_code(next_line),
                     require_annotation: false,
                 });
             }
@@ -266,6 +253,7 @@ fn push_actual_errors(
             for (index, line) in suggested_replacement.lines().enumerate() {
                 errors.push(Error {
                     line_num: Some(span.line_start + index),
+                    column_num: Some(span.column_start),
                     kind: ErrorKind::Suggestion,
                     msg: line.to_string(),
                     // Empty suggestions (suggestions to remove something) are common
@@ -288,6 +276,7 @@ fn push_actual_errors(
         if let Some(label) = &span.label {
             errors.push(Error {
                 line_num: Some(span.line_start),
+                column_num: Some(span.column_start),
                 kind: ErrorKind::Note,
                 msg: label.clone(),
                 // Empty labels (only underlining spans) are common and do not need annotations.
@@ -310,6 +299,7 @@ fn push_backtrace(
     if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
         errors.push(Error {
             line_num: Some(expansion.span.line_start),
+            column_num: Some(expansion.span.column_start),
             kind: ErrorKind::Note,
             msg: format!("in this expansion of {}", expansion.macro_decl_name),
             require_annotation: true,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 42c851ea999..980e89889ab 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -11,7 +11,7 @@ use std::{env, iter, str};
 
 use build_helper::fs::remove_and_create_dir_all;
 use camino::{Utf8Path, Utf8PathBuf};
-use colored::Colorize;
+use colored::{Color, Colorize};
 use regex::{Captures, Regex};
 use tracing::*;
 
@@ -677,9 +677,6 @@ impl<'test> TestCx<'test> {
             return;
         }
 
-        // On Windows, translate all '\' path separators to '/'
-        let file_name = self.testpaths.file.to_string().replace(r"\", "/");
-
         // On Windows, keep all '\' path separators to match the paths reported in the JSON output
         // from the compiler
         let diagnostic_file_name = if self.props.remap_src_base {
@@ -704,6 +701,7 @@ impl<'test> TestCx<'test> {
             .map(|e| Error { msg: self.normalize_output(&e.msg, &[]), ..e });
 
         let mut unexpected = Vec::new();
+        let mut unimportant = Vec::new();
         let mut found = vec![false; expected_errors.len()];
         for actual_error in actual_errors {
             for pattern in &self.props.error_patterns {
@@ -738,14 +736,9 @@ impl<'test> TestCx<'test> {
                         && expected_kinds.contains(&actual_error.kind)
                         && !self.props.dont_require_annotations.contains(&actual_error.kind)
                     {
-                        self.error(&format!(
-                            "{}:{}: unexpected {}: '{}'",
-                            file_name,
-                            actual_error.line_num_str(),
-                            actual_error.kind,
-                            actual_error.msg
-                        ));
                         unexpected.push(actual_error);
+                    } else {
+                        unimportant.push(actual_error);
                     }
                 }
             }
@@ -755,39 +748,140 @@ impl<'test> TestCx<'test> {
         // anything not yet found is a problem
         for (index, expected_error) in expected_errors.iter().enumerate() {
             if !found[index] {
-                self.error(&format!(
-                    "{}:{}: expected {} not found: {}",
-                    file_name,
-                    expected_error.line_num_str(),
-                    expected_error.kind,
-                    expected_error.msg
-                ));
                 not_found.push(expected_error);
             }
         }
 
         if !unexpected.is_empty() || !not_found.is_empty() {
             self.error(&format!(
-                "{} unexpected errors found, {} expected errors not found",
+                "{} unexpected diagnostics reported, {} expected diagnostics not reported",
                 unexpected.len(),
                 not_found.len()
             ));
-            println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
+
+            // Emit locations in a format that is short (relative paths) but "clickable" in editors.
+            // Also normalize path separators to `/`.
+            let file_name = self
+                .testpaths
+                .file
+                .strip_prefix(self.config.src_root.as_str())
+                .unwrap_or(&self.testpaths.file)
+                .to_string()
+                .replace(r"\", "/");
+            let line_str = |e: &Error| {
+                let line_num = e.line_num.map_or("?".to_string(), |line_num| line_num.to_string());
+                // `file:?:NUM` may be confusing to editors and unclickable.
+                let opt_col_num = match e.column_num {
+                    Some(col_num) if line_num != "?" => format!(":{col_num}"),
+                    _ => "".to_string(),
+                };
+                format!("{file_name}:{line_num}{opt_col_num}")
+            };
+            let print_error = |e| println!("{}: {}: {}", line_str(e), e.kind, e.msg.cyan());
+            let push_suggestion =
+                |suggestions: &mut Vec<_>, e: &Error, kind, line, msg, color, rank| {
+                    let mut ret = String::new();
+                    if kind {
+                        ret += &format!("{} {}", "with kind".color(color), e.kind);
+                    }
+                    if line {
+                        if !ret.is_empty() {
+                            ret.push(' ');
+                        }
+                        ret += &format!("{} {}", "on line".color(color), line_str(e));
+                    }
+                    if msg {
+                        if !ret.is_empty() {
+                            ret.push(' ');
+                        }
+                        ret += &format!("{} {}", "with message".color(color), e.msg.cyan());
+                    }
+                    suggestions.push((ret, rank));
+                };
+            let show_suggestions = |mut suggestions: Vec<_>, prefix: &str, color| {
+                // Only show suggestions with the highest rank.
+                suggestions.sort_by_key(|(_, rank)| *rank);
+                if let Some(&(_, top_rank)) = suggestions.first() {
+                    for (suggestion, rank) in suggestions {
+                        if rank == top_rank {
+                            println!("  {} {suggestion}", prefix.color(color));
+                        }
+                    }
+                }
+            };
+
+            // Fuzzy matching quality:
+            // - message and line / message and kind - great, suggested
+            // - only message - good, suggested
+            // - known line and kind - ok, suggested
+            // - only known line - meh, but suggested
+            // - others are not worth suggesting
             if !unexpected.is_empty() {
-                println!("{}", "--- unexpected errors (from JSON output) ---".green());
+                let header = "--- reported in JSON output but not expected in test file ---";
+                println!("{}", header.green());
                 for error in &unexpected {
-                    println!("{}", error.render_for_expected());
+                    print_error(error);
+                    let mut suggestions = Vec::new();
+                    for candidate in &not_found {
+                        let mut push_red_suggestion = |line, msg, rank| {
+                            push_suggestion(
+                                &mut suggestions,
+                                candidate,
+                                candidate.kind != error.kind,
+                                line,
+                                msg,
+                                Color::Red,
+                                rank,
+                            )
+                        };
+                        if error.msg.contains(&candidate.msg) {
+                            push_red_suggestion(candidate.line_num != error.line_num, false, 0);
+                        } else if candidate.line_num.is_some()
+                            && candidate.line_num == error.line_num
+                        {
+                            push_red_suggestion(false, true, 1);
+                        }
+                    }
+
+                    show_suggestions(suggestions, "expected", Color::Red);
                 }
                 println!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                println!("{}", "--- not found errors (from test file) ---".red());
+                let header = "--- expected in test file but not reported in JSON output ---";
+                println!("{}", header.red());
                 for error in &not_found {
-                    println!("{}", error.render_for_expected());
+                    print_error(error);
+                    let mut suggestions = Vec::new();
+                    for candidate in unexpected.iter().chain(&unimportant) {
+                        let mut push_green_suggestion = |line, msg, rank| {
+                            push_suggestion(
+                                &mut suggestions,
+                                candidate,
+                                candidate.kind != error.kind,
+                                line,
+                                msg,
+                                Color::Green,
+                                rank,
+                            )
+                        };
+                        if candidate.msg.contains(&error.msg) {
+                            push_green_suggestion(candidate.line_num != error.line_num, false, 0);
+                        } else if candidate.line_num.is_some()
+                            && candidate.line_num == error.line_num
+                        {
+                            push_green_suggestion(false, true, 1);
+                        }
+                    }
+
+                    show_suggestions(suggestions, "reported", Color::Green);
                 }
-                println!("{}", "---\n".red());
+                println!("{}", "---".red());
             }
-            panic!("errors differ from expected");
+            panic!(
+                "errors differ from expected\nstatus: {}\ncommand: {}\n",
+                proc_res.status, proc_res.cmdline
+            );
         }
     }
 
@@ -2073,7 +2167,6 @@ impl<'test> TestCx<'test> {
             println!("{}", String::from_utf8_lossy(&output.stdout));
             eprintln!("{}", String::from_utf8_lossy(&output.stderr));
         } else {
-            use colored::Colorize;
             eprintln!("warning: no pager configured, falling back to unified diff");
             eprintln!(
                 "help: try configuring a git pager (e.g. `delta`) with `git config --global core.pager delta`"
diff --git a/tests/incremental/issue-61323.rs b/tests/incremental/issue-61323.rs
index b7423c81fc1..4845648d49c 100644
--- a/tests/incremental/issue-61323.rs
+++ b/tests/incremental/issue-61323.rs
@@ -1,7 +1,7 @@
 //@ revisions: rpass cfail
 
 enum A {
-    //[cfail]~^ ERROR 3:1: 3:7: recursive types `A` and `C` have infinite size [E0072]
+    //[cfail]~^ ERROR recursive types `A` and `C` have infinite size [E0072]
     B(C),
 }
 
diff --git a/tests/rustdoc-json/generic-args.rs b/tests/rustdoc-json/generic-args.rs
index 0f588820da7..b4a73a046b5 100644
--- a/tests/rustdoc-json/generic-args.rs
+++ b/tests/rustdoc-json/generic-args.rs
@@ -17,4 +17,7 @@ pub fn my_fn1(_: <MyStruct as MyTrait>::MyType) {}
 //@ is "$.index[?(@.name=='my_fn2')].inner.function.sig.inputs[0][1].dyn_trait.traits[0].trait.args.angle_bracketed.constraints[0].args" null
 pub fn my_fn2(_: IntoIterator<Item = MyStruct, IntoIter = impl Clone>) {}
 
+//@ is "$.index[?(@.name=='my_fn3')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.args.parenthesized.inputs" []
+pub fn my_fn3(f: impl FnMut()) {}
+
 fn main() {}
diff --git a/tests/ui/argument-suggestions/issue-100478.rs b/tests/ui/argument-suggestions/issue-100478.rs
index b0a9703112e..219870f3b23 100644
--- a/tests/ui/argument-suggestions/issue-100478.rs
+++ b/tests/ui/argument-suggestions/issue-100478.rs
@@ -32,8 +32,8 @@ fn four_shuffle(_a: T1, _b: T2, _c: T3, _d: T4) {}
 
 fn main() {
     three_diff(T2::new(0)); //~ ERROR function takes
-    four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR 35:5: 35:17: arguments to this function are incorrect [E0308]
-    four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR 36:5: 36:17: arguments to this function are incorrect [E0308]
+    four_shuffle(T3::default(), T4::default(), T1::default(), T2::default()); //~ ERROR arguments to this function are incorrect [E0308]
+    four_shuffle(T3::default(), T2::default(), T1::default(), T3::default()); //~ ERROR arguments to this function are incorrect [E0308]
 
     let p1 = T1::new(0);
     let p2 = Arc::new(T2::new(0));
diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed
index c74a32e442f..9e5e889506c 100644
--- a/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed
+++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.fixed
@@ -4,5 +4,5 @@
 // Regression test for issue 79694
 
 fn main() {
-    let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
+    let _ = async move { }; //~ ERROR the order of `move` and `async` is incorrect
 }
diff --git a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs
index 81ffbacc327..9c36a6c96da 100644
--- a/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs
+++ b/tests/ui/async-await/incorrect-move-async-order-issue-79694.rs
@@ -4,5 +4,5 @@
 // Regression test for issue 79694
 
 fn main() {
-    let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
+    let _ = move async { }; //~ ERROR the order of `move` and `async` is incorrect
 }
diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs
new file mode 100644
index 00000000000..25b473d5a58
--- /dev/null
+++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs
@@ -0,0 +1,38 @@
+#![feature(rustc_attrs)]
+
+#[rustc_skip_during_method_dispatch]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539]
+trait NotAList {}
+
+#[rustc_skip_during_method_dispatch = "array"]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input [E0539]
+trait AlsoNotAList {}
+
+#[rustc_skip_during_method_dispatch()]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
+trait Argless {}
+
+#[rustc_skip_during_method_dispatch(array, boxed_slice, array)]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
+trait Duplicate {}
+
+#[rustc_skip_during_method_dispatch(slice)]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
+trait Unexpected {}
+
+#[rustc_skip_during_method_dispatch(array = true)]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
+trait KeyValue {}
+
+#[rustc_skip_during_method_dispatch("array")]
+//~^ ERROR: malformed `rustc_skip_during_method_dispatch` attribute input
+trait String {}
+
+#[rustc_skip_during_method_dispatch(array, boxed_slice)]
+trait OK {}
+
+#[rustc_skip_during_method_dispatch(array)]
+//~^ ERROR: attribute should be applied to a trait
+impl OK for () {}
+
+fn main() {}
diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
new file mode 100644
index 00000000000..2f5d7968489
--- /dev/null
+++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr
@@ -0,0 +1,76 @@
+error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:3:1
+   |
+LL | #[rustc_skip_during_method_dispatch]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:7:1
+   |
+LL | #[rustc_skip_during_method_dispatch = "array"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:11:1
+   |
+LL | #[rustc_skip_during_method_dispatch()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--^
+   | |                                  |
+   | |                                  expected at least 1 argument here
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0538]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:15:1
+   |
+LL | #[rustc_skip_during_method_dispatch(array, boxed_slice, array)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^
+   | |                                                       |
+   | |                                                       found `array` used as a key more than once
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0539]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:19:1
+   |
+LL | #[rustc_skip_during_method_dispatch(slice)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^
+   | |                                   |
+   | |                                   valid arguments are `array` or `boxed_slice`
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:23:1
+   |
+LL | #[rustc_skip_during_method_dispatch(array = true)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^
+   | |                                         |
+   | |                                         didn't expect any arguments here
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error[E0565]: malformed `rustc_skip_during_method_dispatch` attribute input
+  --> $DIR/rustc_skip_during_method_dispatch.rs:27:1
+   |
+LL | #[rustc_skip_during_method_dispatch("array")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
+   | |                                   |
+   | |                                   didn't expect a literal here
+   | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]`
+
+error: attribute should be applied to a trait
+  --> $DIR/rustc_skip_during_method_dispatch.rs:34:1
+   |
+LL | #[rustc_skip_during_method_dispatch(array)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | impl OK for () {}
+   | ----------------- not a trait
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0538, E0539, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/tests/ui/compiletest-self-test/line-annotation-mismatches.rs b/tests/ui/compiletest-self-test/line-annotation-mismatches.rs
new file mode 100644
index 00000000000..d2a14374ed4
--- /dev/null
+++ b/tests/ui/compiletest-self-test/line-annotation-mismatches.rs
@@ -0,0 +1,42 @@
+//@ should-fail
+
+// The warning is reported with unknown line
+//@ compile-flags: -D raw_pointer_derive
+//~? WARN kind and unknown line match the reported warning, but we do not suggest it
+
+// The error is expected but not reported at all.
+//~ ERROR this error does not exist
+
+// The error is reported but not expected at all.
+// "`main` function not found in crate" (the main function is intentionally not added)
+
+// An "unimportant" diagnostic is expected on a wrong line.
+//~ ERROR aborting due to
+
+// An "unimportant" diagnostic is expected with a wrong kind.
+//~? ERROR For more information about an error
+
+fn wrong_line_or_kind() {
+    // A diagnostic expected on a wrong line.
+    unresolved1;
+    //~ ERROR cannot find value `unresolved1` in this scope
+
+    // A diagnostic expected with a wrong kind.
+    unresolved2; //~ WARN cannot find value `unresolved2` in this scope
+
+    // A diagnostic expected with a missing kind (treated as a wrong kind).
+    unresolved3; //~ cannot find value `unresolved3` in this scope
+
+    // A diagnostic expected with a wrong line and kind.
+    unresolved4;
+    //~ WARN cannot find value `unresolved4` in this scope
+}
+
+fn wrong_message() {
+    // A diagnostic expected with a wrong message, but the line is known and right.
+    unresolvedA; //~ ERROR stub message 1
+
+    // A diagnostic expected with a wrong message, but the line is known and right,
+    // even if the kind doesn't match.
+    unresolvedB; //~ WARN stub message 2
+}
diff --git a/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr b/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr
new file mode 100644
index 00000000000..7ca3bfaf396
--- /dev/null
+++ b/tests/ui/compiletest-self-test/line-annotation-mismatches.stderr
@@ -0,0 +1,61 @@
+warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+   = note: `#[warn(renamed_and_removed_lints)]` on by default
+
+error[E0425]: cannot find value `unresolved1` in this scope
+  --> $DIR/line-annotation-mismatches.rs:21:5
+   |
+LL |     unresolved1;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `unresolved2` in this scope
+  --> $DIR/line-annotation-mismatches.rs:25:5
+   |
+LL |     unresolved2;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `unresolved3` in this scope
+  --> $DIR/line-annotation-mismatches.rs:28:5
+   |
+LL |     unresolved3;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `unresolved4` in this scope
+  --> $DIR/line-annotation-mismatches.rs:31:5
+   |
+LL |     unresolved4;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `unresolvedA` in this scope
+  --> $DIR/line-annotation-mismatches.rs:37:5
+   |
+LL |     unresolvedA;
+   |     ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `unresolvedB` in this scope
+  --> $DIR/line-annotation-mismatches.rs:41:5
+   |
+LL |     unresolvedB;
+   |     ^^^^^^^^^^^ not found in this scope
+
+warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0601]: `main` function not found in crate `line_annotation_mismatches`
+  --> $DIR/line-annotation-mismatches.rs:42:2
+   |
+LL | }
+   |  ^ consider adding a `main` function to `$DIR/line-annotation-mismatches.rs`
+
+warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok
+   |
+   = note: requested on the command line with `-D raw_pointer_derive`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 7 previous errors; 3 warnings emitted
+
+Some errors have detailed explanations: E0425, E0601.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/feature-gates/feature-gate-cfi_encoding.rs b/tests/ui/feature-gates/feature-gate-cfi_encoding.rs
index 3cef8156014..b6312dd7817 100644
--- a/tests/ui/feature-gates/feature-gate-cfi_encoding.rs
+++ b/tests/ui/feature-gates/feature-gate-cfi_encoding.rs
@@ -1,4 +1,4 @@
 #![crate_type = "lib"]
 
-#[cfi_encoding = "3Bar"] //~ERROR 3:1: 3:25: the `#[cfi_encoding]` attribute is an experimental feature [E0658]
+#[cfi_encoding = "3Bar"] //~ ERROR the `#[cfi_encoding]` attribute is an experimental feature [E0658]
 pub struct Foo(i32);
diff --git a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
index b5fbcc9ccf8..c1469863792 100644
--- a/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
+++ b/tests/ui/feature-gates/feature-gate-unsized_tuple_coercion.rs
@@ -1,4 +1,4 @@
 fn main() {
     let _ : &(dyn Send,) = &((),);
-    //~^ ERROR 2:28: 2:34: mismatched types [E0308]
+    //~^ ERROR mismatched types [E0308]
 }
diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.rs b/tests/ui/impl-header-lifetime-elision/assoc-type.rs
index db3c416540f..14b2ea647f1 100644
--- a/tests/ui/impl-header-lifetime-elision/assoc-type.rs
+++ b/tests/ui/impl-header-lifetime-elision/assoc-type.rs
@@ -9,7 +9,7 @@ trait MyTrait {
 
 impl MyTrait for &i32 {
     type Output = &i32;
-    //~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+    //~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
 }
 
 impl MyTrait for &u32 {
diff --git a/tests/ui/imports/issue-28134.rs b/tests/ui/imports/issue-28134.rs
index 70d3a327c1a..aef2fe8facd 100644
--- a/tests/ui/imports/issue-28134.rs
+++ b/tests/ui/imports/issue-28134.rs
@@ -2,4 +2,4 @@
 
 #![allow(soft_unstable)]
 #![test]
-//~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level
+//~^ ERROR `test` attribute cannot be used at crate level
diff --git a/tests/ui/inference/hint-closure-signature-119266.rs b/tests/ui/inference/hint-closure-signature-119266.rs
index 35be600fd6a..6e136c57cca 100644
--- a/tests/ui/inference/hint-closure-signature-119266.rs
+++ b/tests/ui/inference/hint-closure-signature-119266.rs
@@ -3,7 +3,7 @@ fn main() {
     //~^ NOTE: the found closure
 
     let x: fn(i32) = x;
-    //~^ ERROR: 5:22: 5:23: mismatched types [E0308]
+    //~^ ERROR: mismatched types [E0308]
     //~| NOTE: incorrect number of function parameters
     //~| NOTE: expected due to this
     //~| NOTE: expected fn pointer `fn(i32)`
diff --git a/tests/ui/integral-indexing.rs b/tests/ui/integral-indexing.rs
index f076dfcb0a4..e20553af8a2 100644
--- a/tests/ui/integral-indexing.rs
+++ b/tests/ui/integral-indexing.rs
@@ -3,14 +3,14 @@ pub fn main() {
     let s: String = "abcdef".to_string();
     v[3_usize];
     v[3];
-    v[3u8];  //~ERROR : the type `[isize]` cannot be indexed by `u8`
-    v[3i8];  //~ERROR : the type `[isize]` cannot be indexed by `i8`
-    v[3u32]; //~ERROR : the type `[isize]` cannot be indexed by `u32`
-    v[3i32]; //~ERROR : the type `[isize]` cannot be indexed by `i32`
+    v[3u8];  //~ ERROR the type `[isize]` cannot be indexed by `u8`
+    v[3i8];  //~ ERROR the type `[isize]` cannot be indexed by `i8`
+    v[3u32]; //~ ERROR the type `[isize]` cannot be indexed by `u32`
+    v[3i32]; //~ ERROR the type `[isize]` cannot be indexed by `i32`
     s.as_bytes()[3_usize];
     s.as_bytes()[3];
-    s.as_bytes()[3u8];  //~ERROR : the type `[u8]` cannot be indexed by `u8`
-    s.as_bytes()[3i8];  //~ERROR : the type `[u8]` cannot be indexed by `i8`
-    s.as_bytes()[3u32]; //~ERROR : the type `[u8]` cannot be indexed by `u32`
-    s.as_bytes()[3i32]; //~ERROR : the type `[u8]` cannot be indexed by `i32`
+    s.as_bytes()[3u8];  //~ ERROR the type `[u8]` cannot be indexed by `u8`
+    s.as_bytes()[3i8];  //~ ERROR the type `[u8]` cannot be indexed by `i8`
+    s.as_bytes()[3u32]; //~ ERROR the type `[u8]` cannot be indexed by `u32`
+    s.as_bytes()[3i32]; //~ ERROR the type `[u8]` cannot be indexed by `i32`
 }
diff --git a/tests/ui/issues/issue-92741.rs b/tests/ui/issues/issue-92741.rs
index f2e5fdafd9c..1c5d5810a57 100644
--- a/tests/ui/issues/issue-92741.rs
+++ b/tests/ui/issues/issue-92741.rs
@@ -1,17 +1,17 @@
 //@ run-rustfix
 fn main() {}
 fn _foo() -> bool {
-    &  //~ ERROR 4:5: 6:36: mismatched types [E0308]
+    &  //~ ERROR mismatched types [E0308]
     mut
     if true { true } else { false }
 }
 
 fn _bar() -> bool {
-    &  //~ ERROR 10:5: 11:40: mismatched types [E0308]
+    &  //~ ERROR mismatched types [E0308]
     mut if true { true } else { false }
 }
 
 fn _baz() -> bool {
-    & mut //~ ERROR 15:5: 16:36: mismatched types [E0308]
+    & mut //~ ERROR mismatched types [E0308]
     if true { true } else { false }
 }
diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs
index b3e8ad08ba1..88b8cda0898 100644
--- a/tests/ui/lifetimes/no_lending_iterators.rs
+++ b/tests/ui/lifetimes/no_lending_iterators.rs
@@ -2,7 +2,7 @@ struct Data(String);
 
 impl Iterator for Data {
     type Item = &str;
-    //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+    //~^ ERROR associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
 
     fn next(&mut self) -> Option<Self::Item> {
         Some(&self.0)
@@ -16,7 +16,7 @@ trait Bar {
 
 impl Bar for usize {
     type Item = &usize;
-    //~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
+    //~^ ERROR in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type
 
     fn poke(&mut self, item: Self::Item) {
         self += *item;
@@ -25,7 +25,7 @@ impl Bar for usize {
 
 impl Bar for isize {
     type Item<'a> = &'a isize;
-    //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195]
+    //~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195]
 
     fn poke(&mut self, item: Self::Item) {
         self += *item;
diff --git a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs
index f589e88f68e..0632b822c55 100644
--- a/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs
+++ b/tests/ui/mismatched_types/transforming-option-ref-issue-127545.rs
@@ -2,17 +2,17 @@
 #![crate_type = "lib"]
 
 pub fn foo(arg: Option<&Vec<i32>>) -> Option<&[i32]> {
-    arg //~ ERROR 5:5: 5:8: mismatched types [E0308]
+    arg //~ ERROR mismatched types [E0308]
 }
 
 pub fn bar(arg: Option<&Vec<i32>>) -> &[i32] {
-    arg.unwrap_or(&[]) //~ ERROR 9:19: 9:22: mismatched types [E0308]
+    arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308]
 }
 
 pub fn barzz<'a>(arg: Option<&'a Vec<i32>>, v: &'a [i32]) -> &'a [i32] {
-    arg.unwrap_or(v) //~ ERROR 13:19: 13:20: mismatched types [E0308]
+    arg.unwrap_or(v) //~ ERROR mismatched types [E0308]
 }
 
 pub fn convert_result(arg: Result<&Vec<i32>, ()>) -> &[i32] {
-    arg.unwrap_or(&[]) //~ ERROR 17:19: 17:22: mismatched types [E0308]
+    arg.unwrap_or(&[]) //~ ERROR mismatched types [E0308]
 }
diff --git a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs
index 7ef6bd2f0ac..23ffabad62f 100644
--- a/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs
+++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs
@@ -7,5 +7,5 @@
 #![no_core]
 #![no_main]
 
-#[cfi_encoding] //~ERROR 10:1: 10:16: malformed `cfi_encoding` attribute input
+#[cfi_encoding] //~ ERROR malformed `cfi_encoding` attribute input
 pub struct Type1(i32);
diff --git a/tests/ui/suggestions/issue-105645.rs b/tests/ui/suggestions/issue-105645.rs
index 681ce1c6e37..f3ca8ccbb3c 100644
--- a/tests/ui/suggestions/issue-105645.rs
+++ b/tests/ui/suggestions/issue-105645.rs
@@ -2,7 +2,7 @@ fn main() {
     let mut buf = [0u8; 50];
     let mut bref = buf.as_slice();
     foo(&mut bref);
-    //~^ ERROR 4:9: 4:18: the trait bound `&[u8]: std::io::Write` is not satisfied [E0277]
+    //~^ ERROR the trait bound `&[u8]: std::io::Write` is not satisfied [E0277]
 }
 
 fn foo(_: &mut impl std::io::Write) {}
diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
index 1dfc0786668..807fba0ab7e 100644
--- a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
+++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.rs
@@ -6,5 +6,5 @@ mod option {
 }
 
 fn main() {
-    let _: option::O<()> = (); //~ ERROR 9:28: 9:30: mismatched types [E0308]
+    let _: option::O<()> = (); //~ ERROR mismatched types [E0308]
 }
diff --git a/tests/ui/type/option-ref-advice.rs b/tests/ui/type/option-ref-advice.rs
index 2dcee5a2eb9..435b15d01e3 100644
--- a/tests/ui/type/option-ref-advice.rs
+++ b/tests/ui/type/option-ref-advice.rs
@@ -3,9 +3,9 @@
 fn takes_option(_arg: Option<&String>) {}
 
 fn main() {
-    takes_option(&None); //~ ERROR 6:18: 6:23: mismatched types [E0308]
+    takes_option(&None); //~ ERROR mismatched types [E0308]
 
     let x = String::from("x");
     let res = Some(x);
-    takes_option(&res); //~ ERROR 10:18: 10:22: mismatched types [E0308]
+    takes_option(&res); //~ ERROR mismatched types [E0308]
 }
diff --git a/tests/ui/typeck/issue-100246.rs b/tests/ui/typeck/issue-100246.rs
index 8f0b34bab0c..e05bb2a1362 100644
--- a/tests/ui/typeck/issue-100246.rs
+++ b/tests/ui/typeck/issue-100246.rs
@@ -25,6 +25,6 @@ fn downcast<'a, W: ?Sized>() -> std::io::Result<&'a W> {
 struct Other;
 
 fn main() -> std::io::Result<()> {
-    let other: Other = downcast()?;//~ERROR 28:24: 28:35: `?` operator has incompatible types
+    let other: Other = downcast()?; //~ ERROR `?` operator has incompatible types
     Ok(())
 }
diff --git a/tests/ui/typeck/issue-89275.rs b/tests/ui/typeck/issue-89275.rs
index b91c0017548..6e4211de185 100644
--- a/tests/ui/typeck/issue-89275.rs
+++ b/tests/ui/typeck/issue-89275.rs
@@ -25,5 +25,5 @@ fn downcast<'a, W: ?Sized>() -> &'a W {
 struct Other;
 
 fn main() {
-    let other: &mut Other = downcast();//~ERROR 28:29: 28:39: mismatched types [E0308]
+    let other: &mut Other = downcast();//~ ERROR mismatched types [E0308]
 }