about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs38
-rw-r--r--compiler/rustc_passes/src/stability.rs5
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs53
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs62
-rw-r--r--src/bootstrap/mk/Makefile.in2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile4
-rw-r--r--src/etc/check_missing_items.py58
-rw-r--r--src/librustdoc/clean/types.rs23
-rw-r--r--src/librustdoc/html/render/context.rs5
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/json/conversions.rs48
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs18
-rw-r--r--src/rustdoc-json-types/lib.rs31
-rw-r--r--src/test/rustdoc-json/fns/generic_args.rs12
-rw-r--r--src/test/rustdoc-json/fns/generic_returns.rs2
-rw-r--r--src/test/rustdoc-json/fns/generics.rs6
-rw-r--r--src/test/rustdoc-json/impls/auto.rs18
-rw-r--r--src/test/rustdoc-json/traits/supertrait.rs10
-rw-r--r--src/test/rustdoc-json/type/dyn.rs23
-rw-r--r--src/test/rustdoc-json/type/hrtb.rs2
-rw-r--r--src/test/ui/argument-suggestions/invalid_arguments.stderr20
-rw-r--r--src/test/ui/argument-suggestions/issue-96638.stderr4
-rw-r--r--src/test/ui/argument-suggestions/issue-97484.stderr5
-rw-r--r--src/test/ui/argument-suggestions/too-long.rs41
-rw-r--r--src/test/ui/argument-suggestions/too-long.stderr24
-rw-r--r--src/test/ui/argument-suggestions/two-mismatch-notes.rs11
-rw-r--r--src/test/ui/argument-suggestions/two-mismatch-notes.stderr29
-rw-r--r--src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr8
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.stderr2
-rw-r--r--src/test/ui/async-await/generator-desc.stderr4
-rw-r--r--src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr2
-rw-r--r--src/test/ui/coercion/coerce-to-bang.stderr10
-rw-r--r--src/test/ui/fn/fn-item-type.stderr10
-rw-r--r--src/test/ui/issues/issue-11374.stderr2
-rw-r--r--src/test/ui/issues/issue-18819.stderr10
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr8
-rw-r--r--src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed7
-rw-r--r--src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs7
-rw-r--r--src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr15
-rw-r--r--src/test/ui/resolve/issue-100365.rs50
-rw-r--r--src/test/ui/resolve/issue-100365.stderr54
-rw-r--r--src/test/ui/resolve/issue-22692.rs59
-rw-r--r--src/test/ui/resolve/issue-22692.stderr85
-rw-r--r--src/test/ui/resolve/suggest-path-for-tuple-struct.stderr8
-rw-r--r--src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs52
-rw-r--r--src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr82
-rw-r--r--src/test/ui/span/issue-34264.stderr2
-rw-r--r--src/test/ui/span/missing-unit-argument.stderr4
-rw-r--r--src/test/ui/stability-attribute/auxiliary/ctor-stability.rs8
-rw-r--r--src/test/ui/stability-attribute/ctor-stability.rs8
-rw-r--r--src/test/ui/suggestions/args-instead-of-tuple-errors.stderr18
-rw-r--r--src/test/ui/suggestions/assoc-const-as-field.stderr4
-rw-r--r--src/test/ui/traits/multidispatch-bad.stderr2
-rw-r--r--src/test/ui/tuple/add-tuple-within-arguments.stderr4
-rw-r--r--src/test/ui/tuple/wrong_argument_ice-3.stderr9
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr6
-rw-r--r--src/tools/tidy/src/bins.rs2
-rwxr-xr-xx (renamed from x.sh)0
-rwxr-xr-xx.ps12
-rwxr-xr-xx.py2
63 files changed, 843 insertions, 269 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 20864c657ff..772b81992c4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// E0271, like `src/test/ui/issues/issue-39970.stderr`.
     #[tracing::instrument(
         level = "debug",
-        skip(self, diag, secondary_span, swap_secondary_and_primary, force_label)
+        skip(self, diag, secondary_span, swap_secondary_and_primary, prefer_label)
     )]
     pub fn note_type_err(
         &self,
@@ -1434,7 +1434,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         mut values: Option<ValuePairs<'tcx>>,
         terr: &TypeError<'tcx>,
         swap_secondary_and_primary: bool,
-        force_label: bool,
+        prefer_label: bool,
     ) {
         let span = cause.span();
 
@@ -1612,7 +1612,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             TypeError::ObjectUnsafeCoercion(_) => {}
             _ => {
                 let mut label_or_note = |span: Span, msg: &str| {
-                    if force_label || &[span] == diag.span.primary_spans() {
+                    if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
                         diag.span_label(span, msg);
                     } else {
                         diag.span_note(span, msg);
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 2880ef78c8d..33bebfc2c9a 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2268,7 +2268,7 @@ impl<'a> Parser<'a> {
                     attrs: attrs.into(),
                     ty,
                     pat,
-                    span: lo.to(this.token.span),
+                    span: lo.to(this.prev_token.span),
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index ac55aee9883..c6dd5e7fda3 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -675,14 +675,44 @@ impl<'a> Parser<'a> {
             }
             match parse_item(self) {
                 Ok(None) => {
+                    let is_unnecessary_semicolon = !items.is_empty()
+                        // When the close delim is `)` in a case like the following, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
+                        // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
+                        // This is because the `token.kind` of the close delim is treated as the same as
+                        // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
+                        // Therefore, `token.kind` should not be compared here.
+                        //
+                        // issue-60075.rs
+                        // ```
+                        // trait T {
+                        //     fn qux() -> Option<usize> {
+                        //         let _ = if true {
+                        //         });
+                        //          ^ this close delim
+                        //         Some(4)
+                        //     }
+                        // ```
+                        && self
+                            .span_to_snippet(self.prev_token.span)
+                            .map_or(false, |snippet| snippet == "}")
+                        && self.token.kind == token::Semi;
+                    let semicolon_span = self.token.span;
                     // We have to bail or we'll potentially never make progress.
                     let non_item_span = self.token.span;
                     self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
-                    self.struct_span_err(non_item_span, "non-item in item list")
-                        .span_label(open_brace_span, "item list starts here")
+                    let mut err = self.struct_span_err(non_item_span, "non-item in item list");
+                    err.span_label(open_brace_span, "item list starts here")
                         .span_label(non_item_span, "non-item starts here")
-                        .span_label(self.prev_token.span, "item list ends here")
-                        .emit();
+                        .span_label(self.prev_token.span, "item list ends here");
+                    if is_unnecessary_semicolon {
+                        err.span_suggestion(
+                            semicolon_span,
+                            "consider removing this semicolon",
+                            "",
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    err.emit();
                     break;
                 }
                 Ok(Some(item)) => items.extend(item),
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 34afea0f02e..f884e04a951 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -460,7 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
-                        InheritStability::No,
+                        InheritStability::Yes,
                         |_| {},
                     );
                 }
@@ -600,6 +600,9 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
 
     fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
         self.check_missing_stability(self.tcx.hir().local_def_id(var.id), var.span);
+        if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
+            self.check_missing_stability(self.tcx.hir().local_def_id(ctor_hir_id), var.span);
+        }
         intravisit::walk_variant(self, var);
     }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index cb133841bca..09c1f44826f 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         let ns = source.namespace();
         let is_expected = &|res| source.is_expected(res);
 
-        let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind {
-            ExprKind::Field(_, ident) => {
+        let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| {
+            const MESSAGE: &str = "use the path separator to refer to an item";
+
+            let (lhs_span, rhs_span) = match &expr.kind {
+                ExprKind::Field(base, ident) => (base.span, ident.span),
+                ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
+                _ => return false,
+            };
+
+            if lhs_span.eq_ctxt(rhs_span) {
                 err.span_suggestion(
-                    expr.span,
-                    "use the path separator to refer to an item",
-                    format!("{}::{}", path_str, ident),
+                    lhs_span.between(rhs_span),
+                    MESSAGE,
+                    "::",
                     Applicability::MaybeIncorrect,
                 );
                 true
-            }
-            ExprKind::MethodCall(ref segment, ..) => {
-                let span = expr.span.with_hi(segment.ident.span.hi());
-                err.span_suggestion(
-                    span,
-                    "use the path separator to refer to an item",
-                    format!("{}::{}", path_str, segment.ident),
+            } else if kind == DefKind::Struct
+            && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
+            && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
+            {
+                // The LHS is a type that originates from a macro call.
+                // We have to add angle brackets around it.
+
+                err.span_suggestion_verbose(
+                    lhs_source_span.until(rhs_span),
+                    MESSAGE,
+                    format!("<{snippet}>::"),
                     Applicability::MaybeIncorrect,
                 );
                 true
+            } else {
+                // Either we were unable to obtain the source span / the snippet or
+                // the LHS originates from a macro call and it is not a type and thus
+                // there is no way to replace `.` with `::` and still somehow suggest
+                // valid Rust code.
+
+                false
             }
-            _ => false,
         };
 
         let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| {
@@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             match source {
                 PathSource::Expr(Some(
                     parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
-                )) if path_sep(err, &parent) => {}
+                )) if path_sep(err, &parent, DefKind::Struct) => {}
                 PathSource::Expr(
                     None
                     | Some(Expr {
@@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     }
                 }
             }
-            (Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {
-                if !path_sep(err, &parent) {
+            (
+                Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
+                PathSource::Expr(Some(parent)),
+            ) => {
+                if !path_sep(err, &parent, kind) {
                     return false;
                 }
             }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 1d1f755947f..a7df5320296 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &hir::Expr<'tcx>,
     ) {
         // Next, let's construct the error
-        let (error_span, full_call_span, ctor_of) = match &call_expr.kind {
+        let (error_span, full_call_span, ctor_of, is_method) = match &call_expr.kind {
             hir::ExprKind::Call(
                 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
                 _,
@@ -448,12 +448,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Res::Def(DefKind::Ctor(of, _), _) =
                     self.typeck_results.borrow().qpath_res(qpath, *hir_id)
                 {
-                    (call_span, *span, Some(of))
+                    (call_span, *span, Some(of), false)
                 } else {
-                    (call_span, *span, None)
+                    (call_span, *span, None, false)
                 }
             }
-            hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None),
+            hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, None, false),
             hir::ExprKind::MethodCall(path_segment, _, span) => {
                 let ident_span = path_segment.ident.span;
                 let ident_span = if let Some(args) = path_segment.args {
@@ -461,9 +461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     ident_span
                 };
-                (
-                    *span, ident_span, None, // methods are never ctors
-                )
+                // methods are never ctors
+                (*span, ident_span, None, true)
             }
             k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
         };
@@ -545,7 +544,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty);
             let can_coerce = self.can_coerce(arg_ty, coerced_ty);
             if !can_coerce {
-                return Compatibility::Incompatible(None);
+                return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts(
+                    ty::error::ExpectedFound::new(true, coerced_ty, arg_ty),
+                )));
             }
 
             // Using probe here, since we don't want this subtyping to affect inference.
@@ -659,7 +660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             Applicability::MachineApplicable,
                         );
                     };
-                    self.label_fn_like(&mut err, fn_def_id, callee_ty);
+                    self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(mismatch_idx), is_method);
                     err.emit();
                     return;
                 }
@@ -701,16 +702,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         errors.drain_filter(|error| {
-                let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(error)) = error else { return false };
+                let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
                 let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
                 let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
                 let cause = &self.misc(provided_span);
                 let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
-                if let Some(e) = error {
-                    if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
-                        self.report_and_explain_type_error(trace, e).emit();
-                        return true;
-                    }
+                if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) {
+                    self.report_and_explain_type_error(trace, e).emit();
+                    return true;
                 }
                 false
             });
@@ -749,7 +748,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 format!("arguments to this {} are incorrect", call_name),
             );
             // Call out where the function is defined
-            self.label_fn_like(&mut err, fn_def_id, callee_ty);
+            self.label_fn_like(
+                &mut err,
+                fn_def_id,
+                callee_ty,
+                Some(expected_idx.as_usize()),
+                is_method,
+            );
             err.emit();
             return;
         }
@@ -1031,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // Call out where the function is defined
-        self.label_fn_like(&mut err, fn_def_id, callee_ty);
+        self.label_fn_like(&mut err, fn_def_id, callee_ty, None, is_method);
 
         // And add a suggestion block for all of the parameters
         let suggestion_text = match suggestion_text {
@@ -1781,6 +1786,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err: &mut Diagnostic,
         callable_def_id: Option<DefId>,
         callee_ty: Option<Ty<'tcx>>,
+        // A specific argument should be labeled, instead of all of them
+        expected_idx: Option<usize>,
+        is_method: bool,
     ) {
         let Some(mut def_id) = callable_def_id else {
             return;
@@ -1881,14 +1889,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .get_if_local(def_id)
                 .and_then(|node| node.body_id())
                 .into_iter()
-                .flat_map(|id| self.tcx.hir().body(id).params);
+                .flat_map(|id| self.tcx.hir().body(id).params)
+                .skip(if is_method { 1 } else { 0 });
 
-            for param in params {
+            for (_, param) in params
+                .into_iter()
+                .enumerate()
+                .filter(|(idx, _)| expected_idx.map_or(true, |expected_idx| expected_idx == *idx))
+            {
                 spans.push_span_label(param.span, "");
             }
 
             let def_kind = self.tcx.def_kind(def_id);
             err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+        } else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
+            && let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
+        {
+            let param = expected_idx
+                .and_then(|expected_idx| self.tcx.hir().body(*body).params.get(expected_idx));
+            let (kind, span) = if let Some(param) = param {
+                ("closure parameter", param.span)
+            } else {
+                ("closure", self.tcx.def_span(def_id))
+            };
+            err.span_note(span, &format!("{} defined here", kind));
         } else {
             let def_kind = self.tcx.def_kind(def_id);
             err.span_note(
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 1e0f7e9acf4..9a08a7be0f5 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -80,7 +80,7 @@ TESTS_IN_MINGW_2 := \
 	src/test/ui
 
 ci-mingw-subset-1:
-	$(Q)$(CFG_SRC_DIR)/x.sh test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
+	$(Q)$(CFG_SRC_DIR)/x test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
 ci-mingw-subset-2:
 	$(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2)
 
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile
index 8de9045c3ba..14d0ffd7500 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-12/Dockerfile
@@ -44,7 +44,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-# NOTE: intentionally uses all of `x.py`, `x.sh`, and `x.ps1` to make sure they all work on Linux.
+# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
 ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
            # Run the `mir-opt` tests again but this time for a 32-bit target.
            # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
@@ -52,7 +52,7 @@ ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
            # the PR is approved and tested for merging.
            # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
            # despite having different output on 32-bit vs 64-bit targets.
-           ../x.sh --stage 2 test src/test/mir-opt \
+           ../x --stage 2 test src/test/mir-opt \
                              --host='' --target=i686-unknown-linux-gnu && \
            # Run the UI test suite again, but in `--pass=check` mode
            #
diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py
index a705e238495..ce06a79a21c 100644
--- a/src/etc/check_missing_items.py
+++ b/src/etc/check_missing_items.py
@@ -57,7 +57,7 @@ def check_generic_bound(bound):
     if "trait_bound" in bound:
         for param in bound["trait_bound"]["generic_params"]:
             check_generic_param(param)
-        check_type(bound["trait_bound"]["trait"])
+        check_path(bound["trait_bound"]["trait"])
 
 
 def check_decl(decl):
@@ -66,35 +66,35 @@ def check_decl(decl):
     if decl["output"]:
         check_type(decl["output"])
 
+def check_path(path):
+    args = path["args"]
+    if args:
+        if "angle_bracketed" in args:
+            for arg in args["angle_bracketed"]["args"]:
+                if "type" in arg:
+                    check_type(arg["type"])
+                elif "const" in arg:
+                    check_type(arg["const"]["type"])
+            for binding in args["angle_bracketed"]["bindings"]:
+                if "equality" in binding["binding"]:
+                    term = binding["binding"]["equality"]
+                    if "type" in term: check_type(term["type"])
+                    elif "const" in term: check_type(term["const"])
+                elif "constraint" in binding["binding"]:
+                    for bound in binding["binding"]["constraint"]:
+                        check_generic_bound(bound)
+        elif "parenthesized" in args:
+            for input_ty in args["parenthesized"]["inputs"]:
+                check_type(input_ty)
+            if args["parenthesized"]["output"]:
+                check_type(args["parenthesized"]["output"])
+    if not valid_id(path["id"]):
+        print("Type contained an invalid ID:", path["id"])
+        sys.exit(1)
 
 def check_type(ty):
     if ty["kind"] == "resolved_path":
-        for bound in ty["inner"]["param_names"]:
-            check_generic_bound(bound)
-        args = ty["inner"]["args"]
-        if args:
-            if "angle_bracketed" in args:
-                for arg in args["angle_bracketed"]["args"]:
-                    if "type" in arg:
-                        check_type(arg["type"])
-                    elif "const" in arg:
-                        check_type(arg["const"]["type"])
-                for binding in args["angle_bracketed"]["bindings"]:
-                    if "equality" in binding["binding"]:
-                        term = binding["binding"]["equality"]
-                        if "type" in term: check_type(term["type"])
-                        elif "const" in term: check_type(term["const"])
-                    elif "constraint" in binding["binding"]:
-                        for bound in binding["binding"]["constraint"]:
-                            check_generic_bound(bound)
-            elif "parenthesized" in args:
-                for input_ty in args["parenthesized"]["inputs"]:
-                    check_type(input_ty)
-                if args["parenthesized"]["output"]:
-                    check_type(args["parenthesized"]["output"])
-        if not valid_id(ty["inner"]["id"]):
-            print("Type contained an invalid ID:", ty["inner"]["id"])
-            sys.exit(1)
+        check_path(ty["inner"])
     elif ty["kind"] == "tuple":
         for ty in ty["inner"]:
             check_type(ty)
@@ -111,7 +111,7 @@ def check_type(ty):
         check_decl(ty["inner"]["decl"])
     elif ty["kind"] == "qualified_path":
         check_type(ty["inner"]["self_type"])
-        check_type(ty["inner"]["trait"])
+        check_path(ty["inner"]["trait"])
 
 
 work_list = set([crate["root"]])
@@ -174,7 +174,7 @@ while work_list:
     elif item["kind"] == "impl":
         check_generics(item["inner"]["generics"])
         if item["inner"]["trait"]:
-            check_type(item["inner"]["trait"])
+            check_path(item["inner"]["trait"])
         if item["inner"]["blanket_impl"]:
             check_type(item["inner"]["blanket_impl"])
         check_type(item["inner"]["for"])
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 91d5758077c..1a4786c9b06 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -415,29 +415,28 @@ impl Item {
             .unwrap_or(false)
     }
 
-    pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Span {
+    pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
         let kind = match &*self.kind {
             ItemKind::StrippedItem(k) => k,
             _ => &*self.kind,
         };
         match kind {
-            ItemKind::ModuleItem(Module { span, .. }) => *span,
-            ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
+            ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
+            ItemKind::ImplItem(box Impl { kind: ImplKind::Auto, .. }) => None,
             ItemKind::ImplItem(box Impl { kind: ImplKind::Blanket(_), .. }) => {
                 if let ItemId::Blanket { impl_id, .. } = self.item_id {
-                    rustc_span(impl_id, tcx)
+                    Some(rustc_span(impl_id, tcx))
                 } else {
                     panic!("blanket impl item has non-blanket ID")
                 }
             }
-            _ => {
-                self.item_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
-            }
+            _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)),
         }
     }
 
     pub(crate) fn attr_span(&self, tcx: TyCtxt<'_>) -> rustc_span::Span {
-        crate::passes::span_of_attrs(&self.attrs).unwrap_or_else(|| self.span(tcx).inner())
+        crate::passes::span_of_attrs(&self.attrs)
+            .unwrap_or_else(|| self.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner()))
     }
 
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
@@ -2109,14 +2108,6 @@ impl Span {
         self.0
     }
 
-    pub(crate) fn dummy() -> Self {
-        Self(rustc_span::DUMMY_SP)
-    }
-
-    pub(crate) fn is_dummy(&self) -> bool {
-        self.0.is_dummy()
-    }
-
     pub(crate) fn filename(&self, sess: &Session) -> FileName {
         sess.source_map().span_to_filename(self.0)
     }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 2ed7a6f1bb1..6f029c66c0b 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -301,13 +301,10 @@ impl<'tcx> Context<'tcx> {
     /// may happen, for example, with externally inlined items where the source
     /// of their crate documentation isn't known.
     pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
-        self.href_from_span(item.span(self.tcx()), true)
+        self.href_from_span(item.span(self.tcx())?, true)
     }
 
     pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
-        if span.is_dummy() {
-            return None;
-        }
         let mut root = self.root_path();
         let mut path = String::new();
         let cnum = span.cnum(self.sess());
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 09c54969ef1..5ed5299e09b 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2677,7 +2677,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
         let contents = match fs::read_to_string(&path) {
             Ok(contents) => contents,
             Err(err) => {
-                let span = item.span(tcx).inner();
+                let span = item.span(tcx).map_or(rustc_span::DUMMY_SP, |span| span.inner());
                 tcx.sess
                     .span_err(span, &format!("failed to read file {}: {}", path.display(), err));
                 return false;
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index f508808a8b6..f37c54e4298 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -53,6 +53,7 @@ impl LocalSourcesCollector<'_, '_> {
     fn add_local_source(&mut self, item: &clean::Item) {
         let sess = self.tcx.sess;
         let span = item.span(self.tcx);
+        let Some(span) = span else { return };
         // skip all synthetic "files"
         if !is_real_and_local(span, sess) {
             return;
@@ -109,6 +110,7 @@ impl DocVisitor for SourceCollector<'_, '_> {
 
         let tcx = self.cx.tcx();
         let span = item.span(tcx);
+        let Some(span) = span else { return };
         let sess = tcx.sess;
 
         // If we're not rendering sources, there's nothing to do.
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 4c21fd55328..5f3793ead42 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -59,7 +59,7 @@ impl JsonRenderer<'_> {
             id: from_item_id_with_name(item_id, self.tcx, name),
             crate_id: item_id.krate().as_u32(),
             name: name.map(|sym| sym.to_string()),
-            span: self.convert_span(span),
+            span: span.and_then(|span| self.convert_span(span)),
             visibility: self.convert_visibility(visibility),
             docs,
             attrs,
@@ -428,10 +428,8 @@ impl FromWithTcx<clean::GenericBound> for GenericBound {
         use clean::GenericBound::*;
         match bound {
             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
-                // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
                 GenericBound::TraitBound {
-                    trait_,
+                    trait_: trait_.into_tcx(tcx),
                     generic_params: generic_params.into_tcx(tcx),
                     modifier: from_trait_bound_modifier(modifier),
                 }
@@ -460,12 +458,7 @@ impl FromWithTcx<clean::Type> for Type {
         };
 
         match ty {
-            clean::Type::Path { path } => Type::ResolvedPath {
-                name: path.whole_name(),
-                id: from_item_id(path.def_id().into(), tcx),
-                args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
-                param_names: Vec::new(),
-            },
+            clean::Type::Path { path } => Type::ResolvedPath(path.into_tcx(tcx)),
             clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
                 lifetime: lt.map(convert_lifetime),
                 traits: bounds.into_tcx(tcx),
@@ -487,16 +480,22 @@ impl FromWithTcx<clean::Type> for Type {
                 mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
-            QPath { assoc, self_type, trait_, .. } => {
-                // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-                let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
-                Type::QualifiedPath {
-                    name: assoc.name.to_string(),
-                    args: Box::new(assoc.args.clone().into_tcx(tcx)),
-                    self_type: Box::new((*self_type).into_tcx(tcx)),
-                    trait_: Box::new(trait_),
-                }
-            }
+            QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath {
+                name: assoc.name.to_string(),
+                args: Box::new(assoc.args.clone().into_tcx(tcx)),
+                self_type: Box::new((*self_type).into_tcx(tcx)),
+                trait_: trait_.into_tcx(tcx),
+            },
+        }
+    }
+}
+
+impl FromWithTcx<clean::Path> for Path {
+    fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path {
+        Path {
+            name: path.whole_name(),
+            id: from_item_id(path.def_id().into(), tcx),
+            args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
         }
     }
 }
@@ -565,10 +564,7 @@ impl FromWithTcx<clean::PolyTrait> for PolyTrait {
         clean::PolyTrait { trait_, generic_params }: clean::PolyTrait,
         tcx: TyCtxt<'_>,
     ) -> Self {
-        PolyTrait {
-            trait_: clean::Type::Path { path: trait_ }.into_tcx(tcx),
-            generic_params: generic_params.into_tcx(tcx),
-        }
+        PolyTrait { trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx) }
     }
 }
 
@@ -576,8 +572,6 @@ impl FromWithTcx<clean::Impl> for Impl {
     fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let provided_trait_methods = impl_.provided_trait_methods(tcx);
         let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
-        // FIXME: should `trait_` be a clean::Path equivalent in JSON?
-        let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
         // FIXME: use something like ImplKind in JSON?
         let (synthetic, blanket_impl) = match kind {
             clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None),
@@ -595,7 +589,7 @@ impl FromWithTcx<clean::Impl> for Impl {
                 .into_iter()
                 .map(|x| x.to_string())
                 .collect(),
-            trait_,
+            trait_: trait_.map(|path| path.into_tcx(tcx)),
             for_: for_.into_tcx(tcx),
             items: ids(items, tcx),
             negative: negative_polarity,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 4c6e3eb040d..48835abf952 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -215,7 +215,6 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
                     None,
                 );
 
-                let filename = i.span(self.ctx.tcx).filename(self.ctx.sess());
                 let has_doc_example = tests.found_tests != 0;
                 // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
                 // would presumably panic if a fake `DefIndex` were passed.
@@ -261,13 +260,16 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
                 let should_have_docs = !should_be_ignored
                     && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default));
 
-                debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
-                self.items.entry(filename).or_default().count_item(
-                    has_docs,
-                    has_doc_example,
-                    should_have_doc_example(self.ctx, i),
-                    should_have_docs,
-                );
+                if let Some(span) = i.span(self.ctx.tcx) {
+                    let filename = span.filename(self.ctx.sess());
+                    debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
+                    self.items.entry(filename).or_default().count_item(
+                        has_docs,
+                        has_doc_example,
+                        should_have_doc_example(self.ctx, i),
+                        should_have_docs,
+                    );
+                }
             }
         }
 
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index ecdecadd2ef..7dcad66b1f9 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -9,7 +9,7 @@ use std::path::PathBuf;
 use serde::{Deserialize, Serialize};
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 17;
+pub const FORMAT_VERSION: u32 = 18;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -133,7 +133,7 @@ pub struct DynTrait {
 /// A trait and potential HRTBs
 pub struct PolyTrait {
     #[serde(rename = "trait")]
-    pub trait_: Type,
+    pub trait_: Path,
     /// Used for Higher-Rank Trait Bounds (HRTBs)
     /// ```text
     /// dyn for<'a> Fn() -> &'a i32"
@@ -447,7 +447,7 @@ pub enum WherePredicate {
 pub enum GenericBound {
     TraitBound {
         #[serde(rename = "trait")]
-        trait_: Type,
+        trait_: Path,
         /// Used for Higher-Rank Trait Bounds (HRTBs)
         /// ```text
         /// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
@@ -481,12 +481,7 @@ pub enum Term {
 #[serde(tag = "kind", content = "inner")]
 pub enum Type {
     /// Structs, enums, and traits
-    ResolvedPath {
-        name: String,
-        id: Id,
-        args: Option<Box<GenericArgs>>,
-        param_names: Vec<GenericBound>,
-    },
+    ResolvedPath(Path),
     DynTrait(DynTrait),
     /// Parameterized types
     Generic(String),
@@ -527,11 +522,25 @@ pub enum Type {
         args: Box<GenericArgs>,
         self_type: Box<Type>,
         #[serde(rename = "trait")]
-        trait_: Box<Type>,
+        trait_: Path,
     },
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Path {
+    pub name: String,
+    pub id: Id,
+    /// Generic arguments to the type
+    /// ```test
+    /// std::borrow::Cow<'static, str>
+    ///                 ^^^^^^^^^^^^^^
+    ///                 |
+    ///                 this part
+    /// ```
+    pub args: Option<Box<GenericArgs>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct FunctionPointer {
     pub decl: FnDecl,
     /// Used for Higher-Rank Trait Bounds (HRTBs)
@@ -574,7 +583,7 @@ pub struct Impl {
     pub generics: Generics,
     pub provided_trait_methods: Vec<String>,
     #[serde(rename = "trait")]
-    pub trait_: Option<Type>,
+    pub trait_: Option<Path>,
     #[serde(rename = "for")]
     pub for_: Type,
     pub items: Vec<Id>,
diff --git a/src/test/rustdoc-json/fns/generic_args.rs b/src/test/rustdoc-json/fns/generic_args.rs
index 69150443c29..98ba8e99d82 100644
--- a/src/test/rustdoc-json/fns/generic_args.rs
+++ b/src/test/rustdoc-json/fns/generic_args.rs
@@ -14,7 +14,7 @@ pub trait GenericFoo<'a> {}
 // @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
 // @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null'
 // @count - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1
-// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" '$foo'
+// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
 // @count - "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1
 // @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"'
 // @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"'
@@ -24,12 +24,12 @@ pub fn generics<F: Foo>(f: F) {}
 // @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]"
 // @count - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1
 // @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"'
-// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
 // @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1
 // @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"'
 // @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"'
 // @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1
-// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
@@ -43,11 +43,11 @@ pub fn impl_trait(f: impl Foo) {}
 
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
-// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
 
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
-// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.inner.id" $generic_foo
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
@@ -57,7 +57,7 @@ pub fn impl_trait(f: impl Foo) {}
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
-// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
 // @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
 // @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
diff --git a/src/test/rustdoc-json/fns/generic_returns.rs b/src/test/rustdoc-json/fns/generic_returns.rs
index 1a0f33fe3d2..46f250a99b9 100644
--- a/src/test/rustdoc-json/fns/generic_returns.rs
+++ b/src/test/rustdoc-json/fns/generic_returns.rs
@@ -11,7 +11,7 @@ pub trait Foo {}
 // @is - "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" []
 // @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"'
 // @count - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1
-// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.inner.id" $foo
+// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo
 pub fn get_foo() -> impl Foo {
     Fooer {}
 }
diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs
index e777fabaa52..e55e1e9400d 100644
--- a/src/test/rustdoc-json/fns/generics.rs
+++ b/src/test/rustdoc-json/fns/generics.rs
@@ -10,7 +10,7 @@ pub trait Wham {}
 // @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
 // @is    - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
 // @has   - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
-// @has   - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @has   - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
 // @is    - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
 pub fn one_generic_param_fn<T: Wham>(w: T) {}
 
@@ -18,9 +18,9 @@ pub fn one_generic_param_fn<T: Wham>(w: T) {}
 // @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
 // @is    - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
 // @has   - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
-// @has   - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
+// @has   - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
 // @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
 // @is    - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
 // @is    - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @is    - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id
+// @is    - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id
 pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/src/test/rustdoc-json/impls/auto.rs b/src/test/rustdoc-json/impls/auto.rs
new file mode 100644
index 00000000000..fb32d7c31bc
--- /dev/null
+++ b/src/test/rustdoc-json/impls/auto.rs
@@ -0,0 +1,18 @@
+#![feature(no_core, auto_traits, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub auto trait Bar {}
+
+/// has span
+impl Foo {
+    pub fn baz(&self) {}
+}
+
+// Testing spans, so all tests below code
+// @is auto.json "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null
+// @is - "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]"
+// @is - "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]"
+pub struct Foo;
diff --git a/src/test/rustdoc-json/traits/supertrait.rs b/src/test/rustdoc-json/traits/supertrait.rs
index 486a8e713f8..ce2f3912ba6 100644
--- a/src/test/rustdoc-json/traits/supertrait.rs
+++ b/src/test/rustdoc-json/traits/supertrait.rs
@@ -9,18 +9,18 @@ pub trait Loud {}
 
 // @set very_loud_id = - "$.index[*][?(@.name=='VeryLoud')].id"
 // @count - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1
-// @is -    "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.inner.id" $loud_id
+// @is -    "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id
 pub trait VeryLoud: Loud {}
 
 // @set sounds_good_id = - "$.index[*][?(@.name=='SoundsGood')].id"
 pub trait SoundsGood {}
 
 // @count - "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2
-// @is -    "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.inner.id" $very_loud_id
-// @is -    "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.inner.id" $sounds_good_id
+// @is -    "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id
+// @is -    "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id
 pub trait MetalBand: VeryLoud + SoundsGood {}
 
 // @count - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2
-// @is -    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.inner.id" $very_loud_id
-// @is -    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.inner.id" $sounds_good_id
+// @is -    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id
+// @is -    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id
 pub trait DnabLatem: SoundsGood + VeryLoud {}
diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs
index c18b54d1fdf..690dccc8287 100644
--- a/src/test/rustdoc-json/type/dyn.rs
+++ b/src/test/rustdoc-json/type/dyn.rs
@@ -21,10 +21,10 @@ use std::fmt::Debug;
 // @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" []
 // @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" []
 // @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" []
-// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Fn"'
-// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Send"'
-// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.inner.name" '"Sync"'
-// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"'
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"'
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"'
+// @is    - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
 pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 
 // @is - "$.index[*][?(@.name=='RefFn')].kind" \"typedef\"
@@ -36,14 +36,13 @@ pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 // @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null
 // @count - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1
 // @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.kind" '"resolved_path"'
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.name" '"Fn"'
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.kind" '"borrowed_ref"'
-// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.inner.args.parenthesized.output.inner.lifetime" "\"'b\""
+// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"'
+// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
+// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"'
+// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\""
 pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
 
-// @is    - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.inner.name" '"Send"'
-// @is    - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.inner.name" '"Debug"'
+// @is    - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"'
+// @is    - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"'
 pub type WeirdOrder = Box<dyn Send + Debug>;
diff --git a/src/test/rustdoc-json/type/hrtb.rs b/src/test/rustdoc-json/type/hrtb.rs
index 9311737be0f..5b0c4caee21 100644
--- a/src/test/rustdoc-json/type/hrtb.rs
+++ b/src/test/rustdoc-json/type/hrtb.rs
@@ -19,7 +19,7 @@ where
 // @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null
 // @count - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1
 // @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.inner.name" '"Fn"'
+// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/src/test/ui/argument-suggestions/invalid_arguments.stderr b/src/test/ui/argument-suggestions/invalid_arguments.stderr
index 33f27d48fec..303f0869578 100644
--- a/src/test/ui/argument-suggestions/invalid_arguments.stderr
+++ b/src/test/ui/argument-suggestions/invalid_arguments.stderr
@@ -24,7 +24,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:6:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
-   |    ^^^^^^^^^^^^ -------  -------
+   |    ^^^^^^^^^^^^          -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:17:16
@@ -38,7 +38,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:6:4
    |
 LL | fn two_arg_same(_a: i32, _b: i32) {}
-   |    ^^^^^^^^^^^^ -------  -------
+   |    ^^^^^^^^^^^^ -------
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/invalid_arguments.rs:18:3
@@ -66,7 +66,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:7:4
    |
 LL | fn two_arg_diff(_a: i32, _b: f32) {}
-   |    ^^^^^^^^^^^^ -------  -------
+   |    ^^^^^^^^^^^^          -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:20:16
@@ -80,7 +80,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:7:4
    |
 LL | fn two_arg_diff(_a: i32, _b: f32) {}
-   |    ^^^^^^^^^^^^ -------  -------
+   |    ^^^^^^^^^^^^ -------
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/invalid_arguments.rs:21:3
@@ -108,7 +108,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:8:4
    |
 LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:25:21
@@ -122,7 +122,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:8:4
    |
 LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^          -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:26:26
@@ -136,7 +136,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:8:4
    |
 LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^                   --------
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/invalid_arguments.rs:28:3
@@ -207,7 +207,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:9:4
    |
 LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^^^ -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:35:23
@@ -221,7 +221,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:9:4
    |
 LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^^^          -------
 
 error[E0308]: mismatched types
   --> $DIR/invalid_arguments.rs:36:26
@@ -235,7 +235,7 @@ note: function defined here
   --> $DIR/invalid_arguments.rs:9:4
    |
 LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
-   |    ^^^^^^^^^^^^^^^^ -------  -------  --------
+   |    ^^^^^^^^^^^^^^^^                   --------
 
 error[E0308]: arguments to this function are incorrect
   --> $DIR/invalid_arguments.rs:38:3
diff --git a/src/test/ui/argument-suggestions/issue-96638.stderr b/src/test/ui/argument-suggestions/issue-96638.stderr
index 8af31b8b751..804cb1aa322 100644
--- a/src/test/ui/argument-suggestions/issue-96638.stderr
+++ b/src/test/ui/argument-suggestions/issue-96638.stderr
@@ -2,7 +2,9 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
   --> $DIR/issue-96638.rs:8:5
    |
 LL |     f(&x, "");
-   |     ^ -- an argument of type `usize` is missing
+   |     ^ --  -- expected `usize`, found `&str`
+   |       |
+   |       an argument of type `usize` is missing
    |
 note: function defined here
   --> $DIR/issue-96638.rs:1:4
diff --git a/src/test/ui/argument-suggestions/issue-97484.stderr b/src/test/ui/argument-suggestions/issue-97484.stderr
index 9589e919c0a..b5dedf0f4fa 100644
--- a/src/test/ui/argument-suggestions/issue-97484.stderr
+++ b/src/test/ui/argument-suggestions/issue-97484.stderr
@@ -2,8 +2,9 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied
   --> $DIR/issue-97484.rs:12:5
    |
 LL |     foo(&&A, B, C, D, E, F, G);
-   |     ^^^      -  -        - argument of type `F` unexpected
-   |              |  |
+   |     ^^^      -  -     -  - argument of type `F` unexpected
+   |              |  |     |
+   |              |  |     expected `&E`, found struct `E`
    |              |  argument of type `C` unexpected
    |              argument of type `B` unexpected
    |
diff --git a/src/test/ui/argument-suggestions/too-long.rs b/src/test/ui/argument-suggestions/too-long.rs
new file mode 100644
index 00000000000..7ec56afae1c
--- /dev/null
+++ b/src/test/ui/argument-suggestions/too-long.rs
@@ -0,0 +1,41 @@
+struct Qux;
+
+impl Qux {
+    fn foo(
+        &self,
+        a: i32,
+        b: i32,
+        c: i32,
+        d: i32,
+        e: i32,
+        f: i32,
+        g: i32,
+        h: i32,
+        i: i32,
+        j: i32,
+        k: i32,
+        l: i32,
+    ) {
+    }
+}
+
+fn what(
+    qux: &Qux,
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32,
+    f: &i32,
+    g: i32,
+    h: i32,
+    i: i32,
+    j: i32,
+    k: i32,
+    l: i32,
+) {
+    qux.foo(a, b, c, d, e, f, g, h, i, j, k, l);
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/argument-suggestions/too-long.stderr b/src/test/ui/argument-suggestions/too-long.stderr
new file mode 100644
index 00000000000..bd430194c5e
--- /dev/null
+++ b/src/test/ui/argument-suggestions/too-long.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/too-long.rs:37:28
+   |
+LL |     qux.foo(a, b, c, d, e, f, g, h, i, j, k, l);
+   |         ---                ^ expected `i32`, found `&i32`
+   |         |
+   |         arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $DIR/too-long.rs:4:8
+   |
+LL |     fn foo(
+   |        ^^^
+...
+LL |         f: i32,
+   |         ------
+help: consider dereferencing the borrow
+   |
+LL |     qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l);
+   |                            +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.rs b/src/test/ui/argument-suggestions/two-mismatch-notes.rs
new file mode 100644
index 00000000000..1309041ab9a
--- /dev/null
+++ b/src/test/ui/argument-suggestions/two-mismatch-notes.rs
@@ -0,0 +1,11 @@
+#[derive(Copy, Clone)]
+struct Wrapper<T>(T);
+
+fn foo(_: fn(i32), _: Wrapper<i32>) {}
+
+fn f(_: u32) {}
+
+fn main() {
+    let w = Wrapper::<isize>(1isize);
+    foo(f, w); //~ ERROR arguments to this function are incorrect
+}
diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr
new file mode 100644
index 00000000000..7873cf964cb
--- /dev/null
+++ b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr
@@ -0,0 +1,29 @@
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/two-mismatch-notes.rs:10:5
+   |
+LL |     foo(f, w);
+   |     ^^^
+   |
+note: expected `i32`, found `u32`
+  --> $DIR/two-mismatch-notes.rs:10:9
+   |
+LL |     foo(f, w);
+   |         ^
+   = note: expected fn pointer `fn(i32)`
+                 found fn item `fn(u32) {f}`
+note: expected `i32`, found `isize`
+  --> $DIR/two-mismatch-notes.rs:10:12
+   |
+LL |     foo(f, w);
+   |            ^
+   = note: expected struct `Wrapper<i32>`
+              found struct `Wrapper<isize>`
+note: function defined here
+  --> $DIR/two-mismatch-notes.rs:4:4
+   |
+LL | fn foo(_: fn(i32), _: Wrapper<i32>) {}
+   |    ^^^ ----------  ---------------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
index b904ad102e9..e761c6c62a6 100644
--- a/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-type-projection-from-supertrait.stderr
@@ -10,7 +10,7 @@ note: function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:25:4
    |
 LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
-   |    ^^^^        ----  ---------------
+   |    ^^^^              ---------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:28:23
@@ -24,7 +24,7 @@ note: function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:25:4
    |
 LL | fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
-   |    ^^^^        ----  ---------------
+   |    ^^^^              ---------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:32:28
@@ -38,7 +38,7 @@ note: associated function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:12:8
    |
 LL |     fn chip_paint(&self, c: Self::Color) { }
-   |        ^^^^^^^^^^ -----  --------------
+   |        ^^^^^^^^^^        --------------
 
 error[E0308]: mismatched types
   --> $DIR/associated-type-projection-from-supertrait.rs:33:28
@@ -52,7 +52,7 @@ note: associated function defined here
   --> $DIR/associated-type-projection-from-supertrait.rs:12:8
    |
 LL |     fn chip_paint(&self, c: Self::Color) { }
-   |        ^^^^^^^^^^ -----  --------------
+   |        ^^^^^^^^^^        --------------
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index 1d0b84d31d4..c37d469890c 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -10,7 +10,7 @@ note: function defined here
   --> $DIR/associated-types-path-2.rs:13:8
    |
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
-   |        ^^         ----  -------
+   |        ^^               -------
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     f1(2i32, 4u32);
diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr
index 3be8c552063..2494c3feb2a 100644
--- a/src/test/ui/async-await/generator-desc.stderr
+++ b/src/test/ui/async-await/generator-desc.stderr
@@ -42,7 +42,7 @@ note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
-   |    ^^^                         -----  -----
+   |    ^^^                                -----
 
 error[E0308]: mismatched types
   --> $DIR/generator-desc.rs:14:26
@@ -67,7 +67,7 @@ note: function defined here
   --> $DIR/generator-desc.rs:8:4
    |
 LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
-   |    ^^^                         -----  -----
+   |    ^^^                                -----
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
index 36551e5afc6..5cbdef21831 100644
--- a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
+++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
@@ -12,7 +12,7 @@ note: function defined here
   --> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4
    |
 LL | fn test<T>(_a: T, _b: T) {}
-   |    ^^^^    -----  -----
+   |    ^^^^           -----
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr
index add8f14cfa5..1207dc7e7a2 100644
--- a/src/test/ui/coercion/coerce-to-bang.stderr
+++ b/src/test/ui/coercion/coerce-to-bang.stderr
@@ -12,7 +12,7 @@ note: function defined here
   --> $DIR/coerce-to-bang.rs:3:4
    |
 LL | fn foo(x: usize, y: !, z: usize) { }
-   |    ^^^ --------  ----  --------
+   |    ^^^           ----
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:18:13
@@ -28,7 +28,7 @@ note: function defined here
   --> $DIR/coerce-to-bang.rs:3:4
    |
 LL | fn foo(x: usize, y: !, z: usize) { }
-   |    ^^^ --------  ----  --------
+   |    ^^^           ----
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:26:12
@@ -44,7 +44,7 @@ note: function defined here
   --> $DIR/coerce-to-bang.rs:3:4
    |
 LL | fn foo(x: usize, y: !, z: usize) { }
-   |    ^^^ --------  ----  --------
+   |    ^^^           ----
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:36:12
@@ -60,7 +60,7 @@ note: function defined here
   --> $DIR/coerce-to-bang.rs:3:4
    |
 LL | fn foo(x: usize, y: !, z: usize) { }
-   |    ^^^ --------  ----  --------
+   |    ^^^           ----
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:45:12
@@ -76,7 +76,7 @@ note: function defined here
   --> $DIR/coerce-to-bang.rs:3:4
    |
 LL | fn foo(x: usize, y: !, z: usize) { }
-   |    ^^^ --------  ----  --------
+   |    ^^^           ----
 
 error[E0308]: mismatched types
   --> $DIR/coerce-to-bang.rs:50:21
diff --git a/src/test/ui/fn/fn-item-type.stderr b/src/test/ui/fn/fn-item-type.stderr
index ecc6485d6d2..f03a47d5c2c 100644
--- a/src/test/ui/fn/fn-item-type.stderr
+++ b/src/test/ui/fn/fn-item-type.stderr
@@ -15,7 +15,7 @@ note: function defined here
   --> $DIR/fn-item-type.rs:7:4
    |
 LL | fn eq<T>(x: T, y: T) { }
-   |    ^^    ----  ----
+   |    ^^          ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:22:19
@@ -34,7 +34,7 @@ note: function defined here
   --> $DIR/fn-item-type.rs:7:4
    |
 LL | fn eq<T>(x: T, y: T) { }
-   |    ^^    ----  ----
+   |    ^^          ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:29:23
@@ -53,7 +53,7 @@ note: function defined here
   --> $DIR/fn-item-type.rs:7:4
    |
 LL | fn eq<T>(x: T, y: T) { }
-   |    ^^    ----  ----
+   |    ^^          ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:38:26
@@ -72,7 +72,7 @@ note: function defined here
   --> $DIR/fn-item-type.rs:7:4
    |
 LL | fn eq<T>(x: T, y: T) { }
-   |    ^^    ----  ----
+   |    ^^          ----
 
 error[E0308]: mismatched types
   --> $DIR/fn-item-type.rs:45:19
@@ -90,7 +90,7 @@ note: function defined here
   --> $DIR/fn-item-type.rs:7:4
    |
 LL | fn eq<T>(x: T, y: T) { }
-   |    ^^    ----  ----
+   |    ^^          ----
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/issues/issue-11374.stderr b/src/test/ui/issues/issue-11374.stderr
index 3a1d43310e2..15b2bbeb7c2 100644
--- a/src/test/ui/issues/issue-11374.stderr
+++ b/src/test/ui/issues/issue-11374.stderr
@@ -14,7 +14,7 @@ note: associated function defined here
   --> $DIR/issue-11374.rs:13:12
    |
 LL |     pub fn read_to(&mut self, vec: &mut [u8]) {
-   |            ^^^^^^^ ---------  --------------
+   |            ^^^^^^^            --------------
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr
index 6499dd0d81b..e499d0572f6 100644
--- a/src/test/ui/issues/issue-18819.stderr
+++ b/src/test/ui/issues/issue-18819.stderr
@@ -2,11 +2,13 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-18819.rs:16:5
    |
 LL |     print_x(X);
-   |     ^^^^^^^---
-   |            ||
-   |            |expected reference, found struct `X`
-   |            an argument of type `&str` is missing
+   |     ^^^^^^^--- an argument of type `&str` is missing
    |
+note: expected reference, found struct `X`
+  --> $DIR/issue-18819.rs:16:13
+   |
+LL |     print_x(X);
+   |             ^
    = note: expected reference `&dyn Foo<Item = bool>`
                  found struct `X`
 note: function defined here
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 690fe8fa7af..e9b49c89bf1 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -8,7 +8,7 @@ note: associated function defined here
   --> $DIR/method-call-err-msg.rs:5:8
    |
 LL |     fn zero(self) -> Foo { self }
-   |        ^^^^ ----
+   |        ^^^^
 help: remove the extra argument
    |
 LL |     x.zero()
@@ -24,7 +24,7 @@ note: associated function defined here
   --> $DIR/method-call-err-msg.rs:6:8
    |
 LL |     fn one(self, _: isize) -> Foo { self }
-   |        ^^^ ----  --------
+   |        ^^^       --------
 help: provide the argument
    |
 LL |      .one(/* isize */)
@@ -40,7 +40,7 @@ note: associated function defined here
   --> $DIR/method-call-err-msg.rs:7:8
    |
 LL |     fn two(self, _: isize, _: isize) -> Foo { self }
-   |        ^^^ ----  --------  --------
+   |        ^^^       --------  --------
 help: provide the argument
    |
 LL |      .two(0, /* isize */);
@@ -80,7 +80,7 @@ note: associated function defined here
   --> $DIR/method-call-err-msg.rs:8:8
    |
 LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
-   |        ^^^^^    ----  ----  ----  ----
+   |        ^^^^^          ----  ----  ----
 help: provide the arguments
    |
 LL |     y.three::<usize>(/* usize */, /* usize */, /* usize */);
diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed
new file mode 100644
index 00000000000..63704735490
--- /dev/null
+++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+
+trait Foo {
+    fn bar() {} //~ ERROR non-item in item list
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs
new file mode 100644
index 00000000000..4650b05e20c
--- /dev/null
+++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs
@@ -0,0 +1,7 @@
+// run-rustfix
+
+trait Foo {
+    fn bar() {}; //~ ERROR non-item in item list
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr
new file mode 100644
index 00000000000..396e0c130f1
--- /dev/null
+++ b/src/test/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr
@@ -0,0 +1,15 @@
+error: non-item in item list
+  --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16
+   |
+LL | trait Foo {
+   |           - item list starts here
+LL |     fn bar() {};
+   |                ^
+   |                |
+   |                non-item starts here
+   |                help: consider removing this semicolon
+LL | }
+   | - item list ends here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-100365.rs b/src/test/ui/resolve/issue-100365.rs
new file mode 100644
index 00000000000..1d883503606
--- /dev/null
+++ b/src/test/ui/resolve/issue-100365.rs
@@ -0,0 +1,50 @@
+fn main() {
+    let addr = Into::<std::net::IpAddr>.into([127, 0, 0, 1]);
+    //~^ ERROR expected value, found trait `Into`
+    //~| HELP use the path separator
+
+    let _ = Into.into(());
+    //~^ ERROR expected value, found trait `Into`
+    //~| HELP use the path separator
+
+    let _ = Into::<()>.into;
+    //~^ ERROR expected value, found trait `Into`
+    //~| HELP use the path separator
+}
+
+macro_rules! Trait {
+    () => {
+        ::std::iter::Iterator
+        //~^ ERROR expected value, found trait `std::iter::Iterator`
+        //~| ERROR expected value, found trait `std::iter::Iterator`
+    };
+}
+
+macro_rules! create {
+    () => {
+        Into::<String>.into("")
+        //~^ ERROR expected value, found trait `Into`
+        //~| HELP use the path separator
+    };
+}
+
+fn interaction_with_macros() {
+    //
+    // Note that if the receiver is a macro call, we do not want to suggest to replace
+    // `.` with `::` as that would be a syntax error.
+    // Since the receiver is a trait and not a type, we cannot suggest to surround
+    // it with angle brackets. It would be interpreted as a trait object type void of
+    // `dyn` which is most likely not what the user intended to write.
+    // `<_ as Trait!()>::` is also not an option as it's equally syntactically invalid.
+    //
+
+    Trait!().map(std::convert::identity); // no `help` here!
+
+    Trait!().map; // no `help` here!
+
+    //
+    // Ensure that the suggestion is shown for expressions inside of macro definitions.
+    //
+
+    let _ = create!();
+}
diff --git a/src/test/ui/resolve/issue-100365.stderr b/src/test/ui/resolve/issue-100365.stderr
new file mode 100644
index 00000000000..372d7726668
--- /dev/null
+++ b/src/test/ui/resolve/issue-100365.stderr
@@ -0,0 +1,54 @@
+error[E0423]: expected value, found trait `Into`
+  --> $DIR/issue-100365.rs:2:16
+   |
+LL |     let addr = Into::<std::net::IpAddr>.into([127, 0, 0, 1]);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
+
+error[E0423]: expected value, found trait `Into`
+  --> $DIR/issue-100365.rs:6:13
+   |
+LL |     let _ = Into.into(());
+   |             ^^^^- help: use the path separator to refer to an item: `::`
+
+error[E0423]: expected value, found trait `Into`
+  --> $DIR/issue-100365.rs:10:13
+   |
+LL |     let _ = Into::<()>.into;
+   |             ^^^^^^^^^^- help: use the path separator to refer to an item: `::`
+
+error[E0423]: expected value, found trait `std::iter::Iterator`
+  --> $DIR/issue-100365.rs:17:9
+   |
+LL |         ::std::iter::Iterator
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a value
+...
+LL |     Trait!().map(std::convert::identity); // no `help` here!
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found trait `std::iter::Iterator`
+  --> $DIR/issue-100365.rs:17:9
+   |
+LL |         ::std::iter::Iterator
+   |         ^^^^^^^^^^^^^^^^^^^^^ not a value
+...
+LL |     Trait!().map; // no `help` here!
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found trait `Into`
+  --> $DIR/issue-100365.rs:25:9
+   |
+LL |         Into::<String>.into("")
+   |         ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
+...
+LL |     let _ = create!();
+   |             --------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/issue-22692.rs b/src/test/ui/resolve/issue-22692.rs
index 1d8f442221d..31a76261408 100644
--- a/src/test/ui/resolve/issue-22692.rs
+++ b/src/test/ui/resolve/issue-22692.rs
@@ -1,3 +1,60 @@
 fn main() {
-    let _ = String.new(); //~ ERROR expected value, found struct `String`
+    let _ = String.new();
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = String.default;
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = Vec::<()>.with_capacity(1);
+    //~^ ERROR expected value, found struct `Vec`
+    //~| HELP use the path separator
+}
+
+macro_rules! Type {
+    () => {
+        ::std::cell::Cell
+        //~^ ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+    };
+}
+
+macro_rules! create {
+    (type method) => {
+        Vec.new()
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (type field) => {
+        Vec.new
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (macro method) => {
+        Type!().new(0)
+        //~^ HELP use the path separator
+    };
+}
+
+fn interaction_with_macros() {
+    //
+    // Verify that we do not only suggest to replace `.` with `::` if the receiver is a
+    // macro call but that we also correctly suggest to surround it with angle brackets.
+    //
+
+    Type!().get();
+    //~^ HELP use the path separator
+
+    Type! {}.get;
+    //~^ HELP use the path separator
+
+    //
+    // Ensure that the suggestion is shown for expressions inside of macro definitions.
+    //
+
+    let _ = create!(type method);
+    let _ = create!(type field);
+    let _ = create!(macro method);
 }
diff --git a/src/test/ui/resolve/issue-22692.stderr b/src/test/ui/resolve/issue-22692.stderr
index e076419f68d..6962aa161e9 100644
--- a/src/test/ui/resolve/issue-22692.stderr
+++ b/src/test/ui/resolve/issue-22692.stderr
@@ -2,10 +2,87 @@ error[E0423]: expected value, found struct `String`
   --> $DIR/issue-22692.rs:2:13
    |
 LL |     let _ = String.new();
-   |             ^^^^^^----
-   |             |
-   |             help: use the path separator to refer to an item: `String::new`
+   |             ^^^^^^- help: use the path separator to refer to an item: `::`
 
-error: aborting due to previous error
+error[E0423]: expected value, found struct `String`
+  --> $DIR/issue-22692.rs:6:13
+   |
+LL |     let _ = String.default;
+   |             ^^^^^^- help: use the path separator to refer to an item: `::`
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-22692.rs:10:13
+   |
+LL |     let _ = Vec::<()>.with_capacity(1);
+   |             ^^^^^^^^^- help: use the path separator to refer to an item: `::`
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/issue-22692.rs:17:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type!().get();
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL |     <Type!()>::get();
+   |     ~~~~~~~~~~~
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/issue-22692.rs:17:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type! {}.get;
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL |     <Type! {}>::get;
+   |     ~~~~~~~~~~~~
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-22692.rs:26:9
+   |
+LL |         Vec.new()
+   |         ^^^- help: use the path separator to refer to an item: `::`
+...
+LL |     let _ = create!(type method);
+   |             -------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/issue-22692.rs:31:9
+   |
+LL |         Vec.new
+   |         ^^^- help: use the path separator to refer to an item: `::`
+...
+LL |     let _ = create!(type field);
+   |             ------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/issue-22692.rs:17:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     let _ = create!(macro method);
+   |             --------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL |         <Type!()>::new(0)
+   |         ~~~~~~~~~~~
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr
index 957045ca74b..4764cf2db20 100644
--- a/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr
+++ b/src/test/ui/resolve/suggest-path-for-tuple-struct.stderr
@@ -2,17 +2,13 @@ error[E0423]: expected value, found struct `SomeTupleStruct`
   --> $DIR/suggest-path-for-tuple-struct.rs:22:13
    |
 LL |     let _ = SomeTupleStruct.new();
-   |             ^^^^^^^^^^^^^^^----
-   |             |
-   |             help: use the path separator to refer to an item: `SomeTupleStruct::new`
+   |             ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
 
 error[E0423]: expected value, found struct `SomeRegularStruct`
   --> $DIR/suggest-path-for-tuple-struct.rs:24:13
    |
 LL |     let _ = SomeRegularStruct.new();
-   |             ^^^^^^^^^^^^^^^^^----
-   |             |
-   |             help: use the path separator to refer to an item: `SomeRegularStruct::new`
+   |             ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
index 204a272402d..d5d6b13d62c 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.rs
@@ -16,44 +16,96 @@ pub mod a {
 fn h1() -> i32 {
     a.I
     //~^ ERROR expected value, found module `a`
+    //~| HELP use the path separator
 }
 
 fn h2() -> i32 {
     a.g()
     //~^ ERROR expected value, found module `a`
+    //~| HELP use the path separator
 }
 
 fn h3() -> i32 {
     a.b.J
     //~^ ERROR expected value, found module `a`
+    //~| HELP use the path separator
 }
 
 fn h4() -> i32 {
     a::b.J
     //~^ ERROR expected value, found module `a::b`
+    //~| HELP a constant with a similar name exists
+    //~| HELP use the path separator
 }
 
 fn h5() {
     a.b.f();
     //~^ ERROR expected value, found module `a`
+    //~| HELP use the path separator
     let v = Vec::new();
     v.push(a::b);
     //~^ ERROR expected value, found module `a::b`
+    //~| HELP a constant with a similar name exists
 }
 
 fn h6() -> i32 {
     a::b.f()
     //~^ ERROR expected value, found module `a::b`
+    //~| HELP a constant with a similar name exists
+    //~| HELP use the path separator
 }
 
 fn h7() {
     a::b
     //~^ ERROR expected value, found module `a::b`
+    //~| HELP a constant with a similar name exists
 }
 
 fn h8() -> i32 {
     a::b()
     //~^ ERROR expected function, found module `a::b`
+    //~| HELP a constant with a similar name exists
+}
+
+macro_rules! module {
+    () => {
+        a
+        //~^ ERROR expected value, found module `a`
+        //~| ERROR expected value, found module `a`
+    };
+}
+
+macro_rules! create {
+    (method) => {
+        a.f()
+        //~^ ERROR expected value, found module `a`
+        //~| HELP use the path separator
+    };
+    (field) => {
+        a.f
+        //~^ ERROR expected value, found module `a`
+        //~| HELP use the path separator
+    };
+}
+
+fn h9() {
+    //
+    // Note that if the receiver is a macro call, we do not want to suggest to replace
+    // `.` with `::` as that would be a syntax error.
+    // Since the receiver is a module and not a type, we cannot suggest to surround
+    // it with angle brackets.
+    //
+
+    module!().g::<()>(); // no `help` here!
+
+    module!().g; // no `help` here!
+
+    //
+    // Ensure that the suggestion is shown for expressions inside of macro definitions.
+    //
+
+    let _ = create!(method);
+    let _ = create!(field);
 }
 
 fn main() {}
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index 54b242123eb..a4ce0deeb70 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -2,28 +2,22 @@ error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5
    |
 LL |     a.I
-   |     ^--
-   |     |
-   |     help: use the path separator to refer to an item: `a::I`
+   |     ^- help: use the path separator to refer to an item: `::`
 
 error[E0423]: expected value, found module `a`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5
    |
 LL |     a.g()
-   |     ^--
-   |     |
-   |     help: use the path separator to refer to an item: `a::g`
+   |     ^- help: use the path separator to refer to an item: `::`
 
 error[E0423]: expected value, found module `a`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5
    |
 LL |     a.b.J
-   |     ^--
-   |     |
-   |     help: use the path separator to refer to an item: `a::b`
+   |     ^- help: use the path separator to refer to an item: `::`
 
 error[E0423]: expected value, found module `a::b`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5
    |
 LL |     pub const I: i32 = 1;
    |     --------------------- similarly named constant `I` defined here
@@ -34,22 +28,20 @@ LL |     a::b.J
 help: use the path separator to refer to an item
    |
 LL |     a::b::J
-   |
+   |         ~~
 help: a constant with a similar name exists
    |
 LL |     a::I.J
    |        ~
 
 error[E0423]: expected value, found module `a`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5
    |
 LL |     a.b.f();
-   |     ^--
-   |     |
-   |     help: use the path separator to refer to an item: `a::b`
+   |     ^- help: use the path separator to refer to an item: `::`
 
 error[E0423]: expected value, found module `a::b`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12
    |
 LL |     pub const I: i32 = 1;
    |     --------------------- similarly named constant `I` defined here
@@ -60,7 +52,7 @@ LL |     v.push(a::b);
    |               help: a constant with a similar name exists: `I`
 
 error[E0423]: expected value, found module `a::b`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:52:5
    |
 LL |     pub const I: i32 = 1;
    |     --------------------- similarly named constant `I` defined here
@@ -71,14 +63,14 @@ LL |     a::b.f()
 help: use the path separator to refer to an item
    |
 LL |     a::b::f()
-   |     ~~~~~~~
+   |         ~~
 help: a constant with a similar name exists
    |
 LL |     a::I.f()
    |        ~
 
 error[E0423]: expected value, found module `a::b`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:59:5
    |
 LL |     pub const I: i32 = 1;
    |     --------------------- similarly named constant `I` defined here
@@ -89,7 +81,7 @@ LL |     a::b
    |        help: a constant with a similar name exists: `I`
 
 error[E0423]: expected function, found module `a::b`
-  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:5
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:65:5
    |
 LL |     pub const I: i32 = 1;
    |     --------------------- similarly named constant `I` defined here
@@ -99,6 +91,50 @@ LL |     a::b()
    |        |
    |        help: a constant with a similar name exists: `I`
 
-error: aborting due to 9 previous errors
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9
+   |
+LL |         a
+   |         ^ not a value
+...
+LL |     module!().g::<()>(); // no `help` here!
+   |     --------- in this macro invocation
+   |
+   = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9
+   |
+LL |         a
+   |         ^ not a value
+...
+LL |     module!().g; // no `help` here!
+   |     --------- in this macro invocation
+   |
+   = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9
+   |
+LL |         a.f()
+   |         ^- help: use the path separator to refer to an item: `::`
+...
+LL |     let _ = create!(method);
+   |             --------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found module `a`
+  --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9
+   |
+LL |         a.f
+   |         ^- help: use the path separator to refer to an item: `::`
+...
+LL |     let _ = create!(field);
+   |             -------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index e676d7372e8..28a911d0c5b 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -78,7 +78,7 @@ note: function defined here
   --> $DIR/issue-34264.rs:3:4
    |
 LL | fn bar(x, y: usize) {}
-   |    ^^^ -  --------
+   |    ^^^    --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
index e68260e4a09..d2afd277ecf 100644
--- a/src/test/ui/span/missing-unit-argument.stderr
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -72,7 +72,7 @@ note: associated function defined here
   --> $DIR/missing-unit-argument.rs:6:8
    |
 LL |     fn baz(self, (): ()) { }
-   |        ^^^ ----  ------
+   |        ^^^       ------
 help: provide the argument
    |
 LL |     S.baz(());
@@ -88,7 +88,7 @@ note: associated function defined here
   --> $DIR/missing-unit-argument.rs:7:8
    |
 LL |     fn generic<T>(self, _: T) { }
-   |        ^^^^^^^    ----  ----
+   |        ^^^^^^^          ----
 help: provide the argument
    |
 LL |     S.generic::<()>(());
diff --git a/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs b/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs
new file mode 100644
index 00000000000..74c6023d7fb
--- /dev/null
+++ b/src/test/ui/stability-attribute/auxiliary/ctor-stability.rs
@@ -0,0 +1,8 @@
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![stable(feature = "none", since = "1.0")]
+
+#[stable(feature = "none", since = "1.0")]
+pub enum Foo {
+    A,
+}
diff --git a/src/test/ui/stability-attribute/ctor-stability.rs b/src/test/ui/stability-attribute/ctor-stability.rs
new file mode 100644
index 00000000000..fcab0cb1099
--- /dev/null
+++ b/src/test/ui/stability-attribute/ctor-stability.rs
@@ -0,0 +1,8 @@
+// aux-build:ctor-stability.rs
+// check-pass
+
+extern crate ctor_stability;
+
+fn main() {
+    let _ = ctor_stability::Foo::A;
+}
diff --git a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
index 805c75f464c..4c952669cfa 100644
--- a/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/src/test/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -2,10 +2,13 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:6:34
    |
 LL |     let _: Option<(i32, bool)> = Some(1, 2);
-   |                                  ^^^^ -  - argument of type `{integer}` unexpected
-   |                                       |
-   |                                       expected tuple, found integer
+   |                                  ^^^^    - argument of type `{integer}` unexpected
    |
+note: expected tuple, found integer
+  --> $DIR/args-instead-of-tuple-errors.rs:6:39
+   |
+LL |     let _: Option<(i32, bool)> = Some(1, 2);
+   |                                       ^
    = note: expected tuple `(i32, bool)`
                found type `{integer}`
 note: tuple variant defined here
@@ -22,10 +25,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/args-instead-of-tuple-errors.rs:8:5
    |
 LL |     int_bool(1, 2);
-   |     ^^^^^^^^ -  - argument of type `{integer}` unexpected
-   |              |
-   |              expected tuple, found integer
+   |     ^^^^^^^^    - argument of type `{integer}` unexpected
    |
+note: expected tuple, found integer
+  --> $DIR/args-instead-of-tuple-errors.rs:8:14
+   |
+LL |     int_bool(1, 2);
+   |              ^
    = note: expected tuple `(i32, bool)`
                found type `{integer}`
 note: function defined here
diff --git a/src/test/ui/suggestions/assoc-const-as-field.stderr b/src/test/ui/suggestions/assoc-const-as-field.stderr
index 5e746ecb2f2..78e5634b2de 100644
--- a/src/test/ui/suggestions/assoc-const-as-field.stderr
+++ b/src/test/ui/suggestions/assoc-const-as-field.stderr
@@ -2,9 +2,7 @@ error[E0423]: expected value, found struct `Mod::Foo`
   --> $DIR/assoc-const-as-field.rs:11:9
    |
 LL |     foo(Mod::Foo.Bar);
-   |         ^^^^^^^^----
-   |         |
-   |         help: use the path separator to refer to an item: `Mod::Foo::Bar`
+   |         ^^^^^^^^- help: use the path separator to refer to an item: `::`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/multidispatch-bad.stderr b/src/test/ui/traits/multidispatch-bad.stderr
index 8b6e610067b..d58f1e2d9e5 100644
--- a/src/test/ui/traits/multidispatch-bad.stderr
+++ b/src/test/ui/traits/multidispatch-bad.stderr
@@ -10,7 +10,7 @@ note: function defined here
   --> $DIR/multidispatch-bad.rs:13:4
    |
 LL | fn test<T,U>(_: T, _: U)
-   |    ^^^^      ----  ----
+   |    ^^^^            ----
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     test(22i32, 44u32);
diff --git a/src/test/ui/tuple/add-tuple-within-arguments.stderr b/src/test/ui/tuple/add-tuple-within-arguments.stderr
index 95df96ca0dd..7029d298d71 100644
--- a/src/test/ui/tuple/add-tuple-within-arguments.stderr
+++ b/src/test/ui/tuple/add-tuple-within-arguments.stderr
@@ -8,7 +8,7 @@ note: function defined here
   --> $DIR/add-tuple-within-arguments.rs:1:4
    |
 LL | fn foo(s: &str, a: (i32, i32), s2: &str) {}
-   |    ^^^ -------  -------------  --------
+   |    ^^^          -------------
 help: wrap these arguments in parentheses to construct a tuple
    |
 LL |     foo("hi", (1, 2), "hi");
@@ -28,7 +28,7 @@ note: function defined here
   --> $DIR/add-tuple-within-arguments.rs:3:4
    |
 LL | fn bar(s: &str, a: (&str,), s2: &str) {}
-   |    ^^^ -------  ----------  --------
+   |    ^^^          ----------
 help: use a trailing comma to create a tuple with one element
    |
 LL |     bar("hi", ("hi",), "hi");
diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr
index 2733fb3149b..968cb75db76 100644
--- a/src/test/ui/tuple/wrong_argument_ice-3.stderr
+++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr
@@ -2,10 +2,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/wrong_argument_ice-3.rs:9:16
    |
 LL |         groups.push(new_group, vec![process]);
-   |                ^^^^ ---------  ------------- argument of type `Vec<&Process>` unexpected
-   |                     |
-   |                     expected tuple, found struct `Vec`
+   |                ^^^^            ------------- argument of type `Vec<&Process>` unexpected
    |
+note: expected tuple, found struct `Vec`
+  --> $DIR/wrong_argument_ice-3.rs:9:21
+   |
+LL |         groups.push(new_group, vec![process]);
+   |                     ^^^^^^^^^
    = note: expected tuple `(Vec<String>, Vec<Process>)`
              found struct `Vec<String>`
 note: associated function defined here
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
index 3241c9f8521..455f83f5721 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
@@ -6,11 +6,11 @@ LL |     let z = f(1_usize, 2);
    |             |
    |             arguments to this function are incorrect
    |
-note: closure defined here
-  --> $DIR/unboxed-closures-type-mismatch.rs:4:17
+note: closure parameter defined here
+  --> $DIR/unboxed-closures-type-mismatch.rs:4:18
    |
 LL |     let mut f = |x: isize, y: isize| -> isize { x + y };
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^
 help: change the type of the numeric literal from `usize` to `isize`
    |
 LL |     let z = f(1_isize, 2);
diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs
index 025b8ab9f0a..30903f56d93 100644
--- a/src/tools/tidy/src/bins.rs
+++ b/src/tools/tidy/src/bins.rs
@@ -98,7 +98,7 @@ mod os_impl {
     pub fn check(path: &Path, bad: &mut bool) {
         use std::ffi::OsStr;
 
-        const ALLOWED: &[&str] = &["configure"];
+        const ALLOWED: &[&str] = &["configure", "x"];
 
         crate::walk_no_read(
             path,
diff --git a/x.sh b/x
index 704d0f791f3..704d0f791f3 100755
--- a/x.sh
+++ b/x
diff --git a/x.ps1 b/x.ps1
index 1225443735f..86cea606591 100755
--- a/x.ps1
+++ b/x.ps1
@@ -1,6 +1,6 @@
 #!/usr/bin/env pwsh
 
-# See x.sh for why these scripts exist.
+# See ./x for why these scripts exist.
 
 $xpy = Join-Path $PSScriptRoot x.py
 # Start-Process for some reason splits arguments on spaces. (Isn't powershell supposed to be simpler than bash?)
diff --git a/x.py b/x.py
index 6c68907c581..6df4033d55d 100755
--- a/x.py
+++ b/x.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 # Some systems don't have `python3` in their PATH. This isn't supported by x.py directly;
-# they should use `x.sh` or `x.ps1` instead.
+# they should use `x` or `x.ps1` instead.
 
 # This file is only a "symlink" to bootstrap.py, all logic should go there.