about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs2
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs148
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs11
-rw-r--r--compiler/rustc_driver/src/lib.rs14
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl11
-rw-r--r--compiler/rustc_error_messages/locales/en-US/passes.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs174
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs160
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs46
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs133
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs33
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs10
-rw-r--r--compiler/rustc_interface/src/passes.rs15
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs4
-rw-r--r--compiler/rustc_log/Cargo.toml1
-rw-r--r--compiler/rustc_log/src/lib.rs58
-rw-r--r--compiler/rustc_middle/src/arena.rs7
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/context.rs34
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs11
-rw-r--r--compiler/rustc_passes/src/errors.rs7
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs6
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs7
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6252.stderr9
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--tests/run-make-fulldeps/target-specs/foo.rs2
-rw-r--r--tests/rustdoc-ui/z-help.stdout1
-rw-r--r--tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed14
-rw-r--r--tests/ui/associated-item/ambiguous-associated-type-with-generics.rs14
-rw-r--r--tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr9
-rw-r--r--tests/ui/associated-item/associated-item-duplicate-names-3.stderr2
-rw-r--r--tests/ui/associated-types/associated-types-in-ambiguous-context.stderr25
-rw-r--r--tests/ui/attributes/log-backtrace.rs9
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr8
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr4
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr4
-rw-r--r--tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr4
-rw-r--r--tests/ui/chalkify/impl_wf.stderr8
-rw-r--r--tests/ui/coherence/coherence-overlap-trait-alias.stderr4
-rw-r--r--tests/ui/did_you_mean/bad-assoc-ty.stderr57
-rw-r--r--tests/ui/dst/dst-sized-trait-param.stderr4
-rw-r--r--tests/ui/error-codes/E0223.rs4
-rw-r--r--tests/ui/error-codes/E0223.stderr4
-rw-r--r--tests/ui/error-codes/E0308-2.stderr4
-rw-r--r--tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr9
-rw-r--r--tests/ui/impl-trait/impl_trait_projections.rs2
-rw-r--r--tests/ui/impl-trait/impl_trait_projections.stderr9
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr19
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr19
-rw-r--r--tests/ui/issues/issue-23073.stderr7
-rw-r--r--tests/ui/issues/issue-58712.stderr9
-rw-r--r--tests/ui/issues/issue-65230.stderr4
-rw-r--r--tests/ui/issues/issue-77919.stderr9
-rw-r--r--tests/ui/issues/issue-78622.stderr7
-rw-r--r--tests/ui/issues/issue-86756.stderr2
-rw-r--r--tests/ui/lang-items/start_lang_item_args.argc.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.argv.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr13
-rw-r--r--tests/ui/lang-items/start_lang_item_args.main_args.stderr13
-rw-r--r--tests/ui/lang-items/start_lang_item_args.main_ret.stderr13
-rw-r--r--tests/ui/lang-items/start_lang_item_args.main_ty.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr11
-rw-r--r--tests/ui/lang-items/start_lang_item_args.missing_ret.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr11
-rw-r--r--tests/ui/lang-items/start_lang_item_args.rs101
-rw-r--r--tests/ui/lang-items/start_lang_item_args.sigpipe.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.start_ret.stderr8
-rw-r--r--tests/ui/lang-items/start_lang_item_args.too_many_args.stderr17
-rw-r--r--tests/ui/lint/bare-trait-objects-path.stderr2
-rw-r--r--tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr8
-rw-r--r--tests/ui/marker_trait_attr/region-overlap.stderr8
-rw-r--r--tests/ui/parser/dyn-trait-compatibility.stderr12
-rw-r--r--tests/ui/qualified/qualified-path-params-2.stderr7
-rw-r--r--tests/ui/resolve/issue-103202.stderr7
-rw-r--r--tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs45
-rw-r--r--tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr50
-rw-r--r--tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs5
-rw-r--r--tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr2
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr8
-rw-r--r--tests/ui/self/self-impl.stderr4
-rw-r--r--tests/ui/span/issue-71363.stderr8
-rw-r--r--tests/ui/specialization/min_specialization/issue-79224.stderr4
-rw-r--r--tests/ui/structs/struct-path-associated-type.stderr6
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed28
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs28
-rw-r--r--tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr49
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.stderr7
-rw-r--r--tests/ui/suggestions/type-not-found-in-adt-field.stderr7
-rw-r--r--tests/ui/trait-bounds/unsized-bound.stderr28
-rw-r--r--tests/ui/traits/ignore-err-impls.stderr9
-rw-r--r--tests/ui/traits/impl-bounds-checking.stderr4
-rw-r--r--tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr8
-rw-r--r--tests/ui/traits/issue-43784-supertrait.stderr4
-rw-r--r--tests/ui/traits/issue-50480.stderr27
-rw-r--r--tests/ui/traits/issue-75627.stderr9
-rw-r--r--tests/ui/traits/issue-78372.stderr9
-rw-r--r--tests/ui/traits/issue-91594.stderr4
-rw-r--r--tests/ui/traits/item-privacy.stderr11
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr8
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr8
-rw-r--r--tests/ui/typeck/autoderef-with-param-env-error.stderr8
-rw-r--r--tests/ui/typeck/issue-104513-ice.stderr7
-rw-r--r--tests/ui/ufcs/ufcs-partially-resolved.stderr7
117 files changed, 1623 insertions, 285 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 71adf9b0091..d20f19e60e8 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -8,3 +8,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60
 283abbf0e7d20176f76006825b5c52e9a4234e4c
 # format libstd/sys
 c34fbfaad38cf5829ef5cfe780dc9d58480adeaa
+# move tests
+cf2dff2b1e3fa55fa5415d524200070d0d7aacfe
diff --git a/Cargo.lock b/Cargo.lock
index 4bea3af7f3b..9b3b3951888 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4273,6 +4273,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_span",
  "tracing",
+ "tracing-core",
  "tracing-subscriber",
  "tracing-tree",
 ]
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 2e135aafb1e..41d4a5679f1 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -416,8 +416,7 @@ fn compute_hir_hash(
 
 pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
     let sess = tcx.sess;
-    let krate = tcx.untracked_crate.steal();
-    let mut resolver = tcx.resolver_for_lowering(()).steal();
+    let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
 
     let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
     let mut owners = IndexVec::from_fn_n(
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6658ee89ad6..968c1f49b95 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -6,6 +6,7 @@ use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
+use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -20,7 +21,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty
 use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::DesugaringKind;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 
@@ -29,6 +30,7 @@ use crate::borrowck_errors;
 
 use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
 use crate::diagnostics::find_all_local_uses;
+use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
 use crate::{
     borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
     InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@@ -356,7 +358,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let Some(hir::Node::Item(hir::Item {
             kind: hir::ItemKind::Fn(_, _, body_id),
             ..
-        })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
+        })) = hir.find(self.mir_hir_id())
             && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
         {
             let place = &self.move_data.move_paths[mpi].place;
@@ -948,7 +950,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             (BorrowKind::Mut { .. }, BorrowKind::Shared) => {
                 first_borrow_desc = "immutable ";
-                self.cannot_reborrow_already_borrowed(
+                let mut err = self.cannot_reborrow_already_borrowed(
                     span,
                     &desc_place,
                     &msg_place,
@@ -958,7 +960,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     "immutable",
                     &msg_borrow,
                     None,
-                )
+                );
+                self.suggest_binding_for_closure_capture_self(
+                    &mut err,
+                    issued_borrow.borrowed_place,
+                    &issued_spans,
+                );
+                err
             }
 
             (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
@@ -1240,6 +1248,138 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
+    fn suggest_binding_for_closure_capture_self(
+        &self,
+        err: &mut Diagnostic,
+        borrowed_place: Place<'tcx>,
+        issued_spans: &UseSpans<'tcx>,
+    ) {
+        let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
+        let hir = self.infcx.tcx.hir();
+
+        // check whether the borrowed place is capturing `self` by mut reference
+        let local = borrowed_place.local;
+        let Some(_) = self
+            .body
+            .local_decls
+            .get(local)
+            .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
+
+        struct ExpressionFinder<'hir> {
+            capture_span: Span,
+            closure_change_spans: Vec<Span>,
+            closure_arg_span: Option<Span>,
+            in_closure: bool,
+            suggest_arg: String,
+            hir: rustc_middle::hir::map::Map<'hir>,
+            closure_local_id: Option<hir::HirId>,
+            closure_call_changes: Vec<(Span, String)>,
+        }
+        impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
+            fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
+                if e.span.contains(self.capture_span) {
+                    if let hir::ExprKind::Closure(&hir::Closure {
+                            movability: None,
+                            body,
+                            fn_arg_span,
+                            fn_decl: hir::FnDecl{ inputs, .. },
+                            ..
+                        }) = e.kind &&
+                        let Some(hir::Node::Expr(body )) = self.hir.find(body.hir_id) {
+                            self.suggest_arg = "this: &Self".to_string();
+                            if inputs.len() > 0 {
+                                self.suggest_arg.push_str(", ");
+                            }
+                            self.in_closure = true;
+                            self.closure_arg_span = fn_arg_span;
+                            self.visit_expr(body);
+                            self.in_closure = false;
+                    }
+                }
+                if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e {
+                    if let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path &&
+                        seg.ident.name == kw::SelfLower && self.in_closure {
+                            self.closure_change_spans.push(e.span);
+                    }
+                }
+                hir::intravisit::walk_expr(self, e);
+            }
+
+            fn visit_local(&mut self, local: &'hir hir::Local<'hir>) {
+                if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat &&
+                    let Some(init) = local.init
+                {
+                    if let hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure {
+                            movability: None,
+                            ..
+                        }), .. } = init &&
+                        init.span.contains(self.capture_span) {
+                            self.closure_local_id = Some(*hir_id);
+                    }
+                }
+                hir::intravisit::walk_local(self, local);
+            }
+
+            fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) {
+                if let hir::StmtKind::Semi(e) = s.kind &&
+                    let hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), ..}, args) = e.kind &&
+                    let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path &&
+                    let Res::Local(hir_id) = seg.res &&
+                        Some(hir_id) == self.closure_local_id {
+                        let (span, arg_str) = if args.len() > 0 {
+                            (args[0].span.shrink_to_lo(), "self, ".to_string())
+                        } else {
+                            let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span);
+                            (span, "(self)".to_string())
+                        };
+                        self.closure_call_changes.push((span, arg_str));
+                }
+                hir::intravisit::walk_stmt(self, s);
+            }
+        }
+
+        if let Some(hir::Node::ImplItem(
+                    hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. }
+                )) = hir.find(self.mir_hir_id()) &&
+            let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) {
+            let mut finder = ExpressionFinder {
+                capture_span: *capture_kind_span,
+                closure_change_spans: vec![],
+                closure_arg_span: None,
+                in_closure: false,
+                suggest_arg: String::new(),
+                closure_local_id: None,
+                closure_call_changes: vec![],
+                hir,
+            };
+            finder.visit_expr(expr);
+
+            if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() {
+                return;
+            }
+
+            let mut sugg = vec![];
+            let sm = self.infcx.tcx.sess.source_map();
+
+            if let Some(span) = finder.closure_arg_span {
+                sugg.push((sm.next_point(span.shrink_to_lo()).shrink_to_hi(), finder.suggest_arg));
+            }
+            for span in finder.closure_change_spans {
+                sugg.push((span, "this".to_string()));
+            }
+
+            for (span, suggest) in finder.closure_call_changes {
+                sugg.push((span, suggest));
+            }
+
+            err.multipart_suggestion_verbose(
+                "try explicitly pass `&Self` into the Closure as an argument",
+                sugg,
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
     /// Returns the description of the root place for a conflicting borrow and the full
     /// descriptions of the places that caused the conflict.
     ///
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index b9cfc7e6961..45b15c2c5bd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1094,7 +1094,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     }
 }
 
-fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
+pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
     debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
 
     match local_decl.local_info.as_deref() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index e8a4d1c37c1..f3050a6ef3f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -79,7 +79,7 @@ impl<'tcx> RegionErrors<'tcx> {
     #[track_caller]
     pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
         let val = val.into();
-        self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}");
+        self.1.sess.delay_span_bug(DUMMY_SP, format!("{val:?}"));
         self.0.push(val);
     }
     pub fn is_empty(&self) -> bool {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8ca7103ed48..342abf81f6a 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1231,12 +1231,21 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                     sess.emit_fatal(errors::LinkerFileStem);
                 });
 
+                // Remove any version postfix.
+                let stem = stem
+                    .rsplit_once('-')
+                    .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
+                    .unwrap_or(stem);
+
+                // GCC can have an optional target prefix.
                 let flavor = if stem == "emcc" {
                     LinkerFlavor::EmCc
                 } else if stem == "gcc"
                     || stem.ends_with("-gcc")
+                    || stem == "g++"
+                    || stem.ends_with("-g++")
                     || stem == "clang"
-                    || stem.ends_with("-clang")
+                    || stem == "clang++"
                 {
                     LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
                 } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 16f64235562..a62e5dec4b8 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -231,6 +231,10 @@ fn run_compiler(
         registry: diagnostics_registry(),
     };
 
+    if !tracing::dispatcher::has_been_set() {
+        init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
+    }
+
     match make_input(config.opts.error_format, &matches.free) {
         Err(reported) => return Err(reported),
         Ok(Some((input, input_file_path))) => {
@@ -1300,7 +1304,14 @@ pub fn install_ice_hook() {
 /// This allows tools to enable rust logging without having to magically match rustc's
 /// tracing crate version.
 pub fn init_rustc_env_logger() {
-    if let Err(error) = rustc_log::init_rustc_env_logger() {
+    init_rustc_env_logger_with_backtrace_option(&None);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
+/// choose a target module you wish to show backtraces along with its logging.
+pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
+    if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
         early_error(ErrorOutputType::default(), &error.to_string());
     }
 }
@@ -1366,7 +1377,6 @@ mod signal_handler {
 pub fn main() -> ! {
     let start_time = Instant::now();
     let start_rss = get_resident_set_size();
-    init_rustc_env_logger();
     signal_handler::install();
     let mut callbacks = TimePassesCallbacks::default();
     install_ice_hook();
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
index 0612dbae0b6..ca72b7faa92 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
@@ -46,3 +46,14 @@ hir_typeck_add_missing_parentheses_in_range = you must surround the range in par
 
 hir_typeck_op_trait_generic_params =
     `{$method_name}` must not have any generic parameters
+
+hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
+hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
+
+hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
+    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
+    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 001e53d1d0e..91857dd227d 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -4,6 +4,9 @@
 -passes_see_issue =
     see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
 
+passes_incorrect_do_not_recommend_location =
+    `#[do_not_recommend]` can only be placed on trait implementations
+
 passes_outer_crate_level_attr =
     crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 9fa0e6e8eaa..3521911b055 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -27,6 +27,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
@@ -1643,8 +1644,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn report_ambiguous_associated_type(
         &self,
         span: Span,
-        type_str: &str,
-        trait_str: &str,
+        types: &[String],
+        traits: &[String],
         name: Symbol,
     ) -> ErrorGuaranteed {
         let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
@@ -1655,19 +1656,92 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .keys()
             .any(|full_span| full_span.contains(span))
         {
-            err.span_suggestion(
+            err.span_suggestion_verbose(
                 span.shrink_to_lo(),
                 "you are looking for the module in `std`, not the primitive type",
                 "std::",
                 Applicability::MachineApplicable,
             );
         } else {
-            err.span_suggestion(
-                span,
-                "use fully-qualified syntax",
-                format!("<{} as {}>::{}", type_str, trait_str, name),
-                Applicability::HasPlaceholders,
-            );
+            match (types, traits) {
+                ([], []) => {
+                    err.span_suggestion_verbose(
+                        span,
+                        &format!(
+                            "if there were a type named `Type` that implements a trait named \
+                             `Trait` with associated type `{name}`, you could use the \
+                             fully-qualified path",
+                        ),
+                        format!("<Type as Trait>::{name}"),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+                ([], [trait_str]) => {
+                    err.span_suggestion_verbose(
+                        span,
+                        &format!(
+                            "if there were a type named `Example` that implemented `{trait_str}`, \
+                             you could use the fully-qualified path",
+                        ),
+                        format!("<Example as {trait_str}>::{name}"),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+                ([], traits) => {
+                    err.span_suggestions(
+                        span,
+                        &format!(
+                            "if there were a type named `Example` that implemented one of the \
+                             traits with associated type `{name}`, you could use the \
+                             fully-qualified path",
+                        ),
+                        traits
+                            .iter()
+                            .map(|trait_str| format!("<Example as {trait_str}>::{name}"))
+                            .collect::<Vec<_>>(),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+                ([type_str], []) => {
+                    err.span_suggestion_verbose(
+                        span,
+                        &format!(
+                            "if there were a trait named `Example` with associated type `{name}` \
+                             implemented for `{type_str}`, you could use the fully-qualified path",
+                        ),
+                        format!("<{type_str} as Example>::{name}"),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+                (types, []) => {
+                    err.span_suggestions(
+                        span,
+                        &format!(
+                            "if there were a trait named `Example` with associated type `{name}` \
+                             implemented for one of the types, you could use the fully-qualified \
+                             path",
+                        ),
+                        types
+                            .into_iter()
+                            .map(|type_str| format!("<{type_str} as Example>::{name}")),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+                (types, traits) => {
+                    let mut suggestions = vec![];
+                    for type_str in types {
+                        for trait_str in traits {
+                            suggestions.push(format!("<{type_str} as {trait_str}>::{name}"));
+                        }
+                    }
+                    err.span_suggestions(
+                        span,
+                        "use the fully-qualified path",
+                        suggestions,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
         }
         err.emit()
     }
@@ -2050,12 +2124,64 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     err.emit()
                 } else if let Err(reported) = qself_ty.error_reported() {
                     reported
+                } else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() {
+                    // `<impl Trait as OtherTrait>::Assoc` makes no sense.
+                    struct_span_err!(
+                        tcx.sess,
+                        tcx.def_span(alias_ty.def_id),
+                        E0667,
+                        "`impl Trait` is not allowed in path parameters"
+                    )
+                    .emit() // Already reported in an earlier stage.
                 } else {
+                    // Find all the `impl`s that `qself_ty` has for any trait that has the
+                    // associated type, so that we suggest the right one.
+                    let infcx = tcx.infer_ctxt().build();
+                    // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()`
+                    // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`.
+                    let param_env = ty::ParamEnv::empty();
+                    let traits: Vec<_> = self
+                        .tcx()
+                        .all_traits()
+                        .filter(|trait_def_id| {
+                            // Consider only traits with the associated type
+                            tcx.associated_items(*trait_def_id)
+                                .in_definition_order()
+                                .any(|i| {
+                                    i.kind.namespace() == Namespace::TypeNS
+                                        && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
+                                        && matches!(i.kind, ty::AssocKind::Type)
+                                })
+                            // Consider only accessible traits
+                            && tcx.visibility(*trait_def_id)
+                                .is_accessible_from(self.item_def_id(), tcx)
+                            && tcx.all_impls(*trait_def_id)
+                                .any(|impl_def_id| {
+                                    let trait_ref = tcx.bound_impl_trait_ref(impl_def_id);
+                                    trait_ref.map_or(false, |trait_ref| {
+                                        let impl_ = trait_ref.subst(
+                                            tcx,
+                                            infcx.fresh_substs_for_item(span, impl_def_id),
+                                        );
+                                        infcx
+                                            .can_eq(
+                                                param_env,
+                                                tcx.erase_regions(impl_.self_ty()),
+                                                tcx.erase_regions(qself_ty),
+                                            )
+                                            .is_ok()
+                                    })
+                                    && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
+                                })
+                        })
+                        .map(|trait_def_id| tcx.def_path_str(trait_def_id))
+                        .collect();
+
                     // Don't print `TyErr` to the user.
                     self.report_ambiguous_associated_type(
                         span,
-                        &qself_ty.to_string(),
-                        "Trait",
+                        &[qself_ty.to_string()],
+                        &traits,
                         assoc_ident.name,
                     )
                 };
@@ -2173,16 +2299,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let is_part_of_self_trait_constraints = def_id == trait_def_id;
             let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id);
 
-            let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
-                "Self"
+            let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
+                vec!["Self".to_string()]
             } else {
-                "Type"
+                // Find all the types that have an `impl` for the trait.
+                tcx.all_impls(trait_def_id)
+                    .filter(|impl_def_id| {
+                        // Consider only accessible traits
+                        tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx)
+                            && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
+                    })
+                    .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
+                    .map(|impl_| impl_.self_ty())
+                    // We don't care about blanket impls.
+                    .filter(|self_ty| !self_ty.has_non_region_param())
+                    .map(|self_ty| tcx.erase_regions(self_ty).to_string())
+                    .collect()
             };
-
+            // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
+            // references the trait. Relevant for the first case in
+            // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
             let reported = self.report_ambiguous_associated_type(
                 span,
-                type_name,
-                &path_str,
+                &type_names,
+                &[path_str],
                 item_segment.ident.name,
             );
             return tcx.ty_error_with_guaranteed(reported)
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 7af89934d14..2cdf7579471 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2,7 +2,9 @@ use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, LocalDefId};
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{
+    pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
@@ -320,15 +322,6 @@ fn compare_method_predicate_entailment<'tcx>(
             ty::Binder::dummy(ty::PredicateKind::WellFormed(unnormalized_impl_fty.into())),
         ));
     }
-    let emit_implied_wf_lint = || {
-        infcx.tcx.struct_span_lint_hir(
-            rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT,
-            impl_m_hir_id,
-            infcx.tcx.def_span(impl_m.def_id),
-            "impl method assumes more implied bounds than the corresponding trait method",
-            |lint| lint,
-        );
-    };
 
     // Check that all obligations are satisfied by the implementation's
     // version.
@@ -346,7 +339,7 @@ fn compare_method_predicate_entailment<'tcx>(
                 )
                 .map(|()| {
                     // If the skip-mode was successful, emit a lint.
-                    emit_implied_wf_lint();
+                    emit_implied_wf_lint(infcx.tcx, impl_m, impl_m_hir_id, vec![]);
                 });
             }
             CheckImpliedWfMode::Skip => {
@@ -382,8 +375,16 @@ fn compare_method_predicate_entailment<'tcx>(
                     CheckImpliedWfMode::Skip,
                 )
                 .map(|()| {
+                    let bad_args = extract_bad_args_for_implies_lint(
+                        tcx,
+                        &errors,
+                        (trait_m, trait_sig),
+                        // Unnormalized impl sig corresponds to the HIR types written
+                        (impl_m, unnormalized_impl_sig),
+                        impl_m_hir_id,
+                    );
                     // If the skip-mode was successful, emit a lint.
-                    emit_implied_wf_lint();
+                    emit_implied_wf_lint(tcx, impl_m, impl_m_hir_id, bad_args);
                 });
             }
             CheckImpliedWfMode::Skip => {
@@ -400,6 +401,141 @@ fn compare_method_predicate_entailment<'tcx>(
     Ok(())
 }
 
+fn extract_bad_args_for_implies_lint<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    errors: &[infer::RegionResolutionError<'tcx>],
+    (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+    (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+    hir_id: hir::HirId,
+) -> Vec<(Span, Option<String>)> {
+    let mut blame_generics = vec![];
+    for error in errors {
+        // Look for the subregion origin that contains an input/output type
+        let origin = match error {
+            infer::RegionResolutionError::ConcreteFailure(o, ..) => o,
+            infer::RegionResolutionError::GenericBoundFailure(o, ..) => o,
+            infer::RegionResolutionError::SubSupConflict(_, _, o, ..) => o,
+            infer::RegionResolutionError::UpperBoundUniverseConflict(.., o, _) => o,
+        };
+        // Extract (possible) input/output types from origin
+        match origin {
+            infer::SubregionOrigin::Subtype(trace) => {
+                if let Some((a, b)) = trace.values.ty() {
+                    blame_generics.extend([a, b]);
+                }
+            }
+            infer::SubregionOrigin::RelateParamBound(_, ty, _) => blame_generics.push(*ty),
+            infer::SubregionOrigin::ReferenceOutlivesReferent(ty, _) => blame_generics.push(*ty),
+            _ => {}
+        }
+    }
+
+    let fn_decl = tcx.hir().fn_decl_by_hir_id(hir_id).unwrap();
+    let opt_ret_ty = match fn_decl.output {
+        hir::FnRetTy::DefaultReturn(_) => None,
+        hir::FnRetTy::Return(ty) => Some(ty),
+    };
+
+    // Map late-bound regions from trait to impl, so the names are right.
+    let mapping = std::iter::zip(
+        tcx.fn_sig(trait_m.def_id).bound_vars(),
+        tcx.fn_sig(impl_m.def_id).bound_vars(),
+    )
+    .filter_map(|(impl_bv, trait_bv)| {
+        if let ty::BoundVariableKind::Region(impl_bv) = impl_bv
+            && let ty::BoundVariableKind::Region(trait_bv) = trait_bv
+        {
+            Some((impl_bv, trait_bv))
+        } else {
+            None
+        }
+    })
+    .collect();
+
+    // For each arg, see if it was in the "blame" of any of the region errors.
+    // If so, then try to produce a suggestion to replace the argument type with
+    // one from the trait.
+    let mut bad_args = vec![];
+    for (idx, (ty, hir_ty)) in
+        std::iter::zip(impl_sig.inputs_and_output, fn_decl.inputs.iter().chain(opt_ret_ty))
+            .enumerate()
+    {
+        let expected_ty = trait_sig.inputs_and_output[idx]
+            .fold_with(&mut RemapLateBound { tcx, mapping: &mapping });
+        if blame_generics.iter().any(|blame| ty.contains(*blame)) {
+            let expected_ty_sugg = expected_ty.to_string();
+            bad_args.push((
+                hir_ty.span,
+                // Only suggest something if it actually changed.
+                (expected_ty_sugg != ty.to_string()).then_some(expected_ty_sugg),
+            ));
+        }
+    }
+
+    bad_args
+}
+
+struct RemapLateBound<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    mapping: &'a FxHashMap<ty::BoundRegionKind, ty::BoundRegionKind>,
+}
+
+impl<'tcx> TypeFolder<'tcx> for RemapLateBound<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        if let ty::ReFree(fr) = *r {
+            self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
+                bound_region: self
+                    .mapping
+                    .get(&fr.bound_region)
+                    .copied()
+                    .unwrap_or(fr.bound_region),
+                ..fr
+            }))
+        } else {
+            r
+        }
+    }
+}
+
+fn emit_implied_wf_lint<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_m: &ty::AssocItem,
+    hir_id: hir::HirId,
+    bad_args: Vec<(Span, Option<String>)>,
+) {
+    let span: MultiSpan = if bad_args.is_empty() {
+        tcx.def_span(impl_m.def_id).into()
+    } else {
+        bad_args.iter().map(|(span, _)| *span).collect::<Vec<_>>().into()
+    };
+    tcx.struct_span_lint_hir(
+        rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT,
+        hir_id,
+        span,
+        "impl method assumes more implied bounds than the corresponding trait method",
+        |lint| {
+            let bad_args: Vec<_> =
+                bad_args.into_iter().filter_map(|(span, sugg)| Some((span, sugg?))).collect();
+            if !bad_args.is_empty() {
+                lint.multipart_suggestion(
+                    format!(
+                        "replace {} type{} to make the impl signature compatible",
+                        pluralize!("this", bad_args.len()),
+                        pluralize!(bad_args.len())
+                    ),
+                    bad_args,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            lint
+        },
+    );
+}
+
 #[derive(Debug, PartialEq, Eq)]
 enum CheckImpliedWfMode {
     /// Checks implied well-formedness of the impl method. If it fails, we will
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d1f4dbc8d84..92fd4625ee8 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1254,7 +1254,11 @@ fn check_impl<'tcx>(
                 // therefore don't need to be WF (the trait's `Self: Trait` predicate
                 // won't hold).
                 let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap();
-                let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
+                let trait_ref = wfcx.normalize(
+                    ast_trait_ref.path.span,
+                    Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
+                    trait_ref,
+                );
                 let trait_pred = ty::TraitPredicate {
                     trait_ref,
                     constness: match constness {
@@ -1263,7 +1267,7 @@ fn check_impl<'tcx>(
                     },
                     polarity: ty::ImplPolarity::Positive,
                 };
-                let obligations = traits::wf::trait_obligations(
+                let mut obligations = traits::wf::trait_obligations(
                     wfcx.infcx,
                     wfcx.param_env,
                     wfcx.body_id,
@@ -1271,6 +1275,13 @@ fn check_impl<'tcx>(
                     ast_trait_ref.path.span,
                     item,
                 );
+                for obligation in &mut obligations {
+                    if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred()
+                        && pred.self_ty().skip_binder() == trait_ref.self_ty()
+                    {
+                        obligation.cause.span = ast_self_ty.span;
+                    }
+                }
                 debug!(?obligations);
                 wfcx.register_obligations(obligations);
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 4f9d5826583..2dbfc1bc9a2 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -114,34 +114,46 @@ fn diagnostic_hir_wf_check<'tcx>(
     // Get the starting `hir::Ty` using our `WellFormedLoc`.
     // We will walk 'into' this type to try to find
     // a more precise span for our predicate.
-    let ty = match loc {
+    let tys = match loc {
         WellFormedLoc::Ty(_) => match hir.get(hir_id) {
             hir::Node::ImplItem(item) => match item.kind {
-                hir::ImplItemKind::Type(ty) => Some(ty),
-                hir::ImplItemKind::Const(ty, _) => Some(ty),
+                hir::ImplItemKind::Type(ty) => vec![ty],
+                hir::ImplItemKind::Const(ty, _) => vec![ty],
                 ref item => bug!("Unexpected ImplItem {:?}", item),
             },
             hir::Node::TraitItem(item) => match item.kind {
-                hir::TraitItemKind::Type(_, ty) => ty,
-                hir::TraitItemKind::Const(ty, _) => Some(ty),
+                hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(),
+                hir::TraitItemKind::Const(ty, _) => vec![ty],
                 ref item => bug!("Unexpected TraitItem {:?}", item),
             },
             hir::Node::Item(item) => match item.kind {
-                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty),
-                hir::ItemKind::Impl(ref impl_) => {
-                    assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_);
-                    Some(impl_.self_ty)
-                }
+                hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty],
+                hir::ItemKind::Impl(ref impl_) => match &impl_.of_trait {
+                    Some(t) => t
+                        .path
+                        .segments
+                        .last()
+                        .iter()
+                        .flat_map(|seg| seg.args().args)
+                        .filter_map(|arg| {
+                            if let hir::GenericArg::Type(ty) = arg { Some(*ty) } else { None }
+                        })
+                        .chain([impl_.self_ty])
+                        .collect(),
+                    None => {
+                        vec![impl_.self_ty]
+                    }
+                },
                 ref item => bug!("Unexpected item {:?}", item),
             },
-            hir::Node::Field(field) => Some(field.ty),
+            hir::Node::Field(field) => vec![field.ty],
             hir::Node::ForeignItem(ForeignItem {
                 kind: ForeignItemKind::Static(ty, _), ..
-            }) => Some(*ty),
+            }) => vec![*ty],
             hir::Node::GenericParam(hir::GenericParam {
                 kind: hir::GenericParamKind::Type { default: Some(ty), .. },
                 ..
-            }) => Some(*ty),
+            }) => vec![*ty],
             ref node => bug!("Unexpected node {:?}", node),
         },
         WellFormedLoc::Param { function: _, param_idx } => {
@@ -149,16 +161,16 @@ fn diagnostic_hir_wf_check<'tcx>(
             // Get return type
             if param_idx as usize == fn_decl.inputs.len() {
                 match fn_decl.output {
-                    hir::FnRetTy::Return(ty) => Some(ty),
+                    hir::FnRetTy::Return(ty) => vec![ty],
                     // The unit type `()` is always well-formed
-                    hir::FnRetTy::DefaultReturn(_span) => None,
+                    hir::FnRetTy::DefaultReturn(_span) => vec![],
                 }
             } else {
-                Some(&fn_decl.inputs[param_idx as usize])
+                vec![&fn_decl.inputs[param_idx as usize]]
             }
         }
     };
-    if let Some(ty) = ty {
+    for ty in tys {
         visitor.visit_ty(ty);
     }
     visitor.cause
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 32f86b8042c..57feefbcab6 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -1,4 +1,7 @@
 use crate::coercion::CoerceMany;
+use crate::errors::{
+    LangStartIncorrectNumberArgs, LangStartIncorrectParam, LangStartIncorrectRetTy,
+};
 use crate::gather_locals::GatherLocalsVisitor;
 use crate::FnCtxt;
 use crate::GeneratorTypes;
@@ -9,8 +12,9 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::check::fn_maybe_err;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::RegionVariableOrigin;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
+use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use std::cell::RefCell;
 
@@ -168,6 +172,10 @@ pub(super) fn check_fn<'a, 'tcx>(
         check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
     }
 
+    if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == hir.local_def_id(fn_id).to_def_id() {
+        check_lang_start_fn(tcx, fn_sig, decl, fn_def_id);
+    }
+
     gen_ty
 }
 
@@ -223,3 +231,126 @@ fn check_panic_info_fn(
         tcx.sess.span_err(span, "should have no const parameters");
     }
 }
+
+fn check_lang_start_fn<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    fn_sig: ty::FnSig<'tcx>,
+    decl: &'tcx hir::FnDecl<'tcx>,
+    def_id: LocalDefId,
+) {
+    let inputs = fn_sig.inputs();
+
+    let arg_count = inputs.len();
+    if arg_count != 4 {
+        tcx.sess.emit_err(LangStartIncorrectNumberArgs {
+            params_span: tcx.def_span(def_id),
+            found_param_count: arg_count,
+        });
+    }
+
+    // only check args if they should exist by checking the count
+    // note: this does not handle args being shifted or their order swapped very nicely
+    // but it's a lang item, users shouldn't frequently encounter this
+
+    // first arg is `main: fn() -> T`
+    if let Some(&main_arg) = inputs.get(0) {
+        // make a Ty for the generic on the fn for diagnostics
+        // FIXME: make the lang item generic checks check for the right generic *kind*
+        // for example `start`'s generic should be a type parameter
+        let generics = tcx.generics_of(def_id);
+        let fn_generic = generics.param_at(0, tcx);
+        let generic_tykind =
+            ty::Param(ty::ParamTy { index: fn_generic.index, name: fn_generic.name });
+        let generic_ty = tcx.mk_ty(generic_tykind);
+        let expected_fn_sig =
+            tcx.mk_fn_sig([].iter(), &generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
+        let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig));
+
+        // we emit the same error to suggest changing the arg no matter what's wrong with the arg
+        let emit_main_fn_arg_err = || {
+            tcx.sess.emit_err(LangStartIncorrectParam {
+                param_span: decl.inputs[0].span,
+                param_num: 1,
+                expected_ty: expected_ty,
+                found_ty: main_arg,
+            });
+        };
+
+        if let ty::FnPtr(main_fn_sig) = main_arg.kind() {
+            let main_fn_inputs = main_fn_sig.inputs();
+            if main_fn_inputs.iter().count() != 0 {
+                emit_main_fn_arg_err();
+            }
+
+            let output = main_fn_sig.output();
+            output.map_bound(|ret_ty| {
+                // if the output ty is a generic, it's probably the right one
+                if !matches!(ret_ty.kind(), ty::Param(_)) {
+                    emit_main_fn_arg_err();
+                }
+            });
+        } else {
+            emit_main_fn_arg_err();
+        }
+    }
+
+    // second arg is isize
+    if let Some(&argc_arg) = inputs.get(1) {
+        if argc_arg != tcx.types.isize {
+            tcx.sess.emit_err(LangStartIncorrectParam {
+                param_span: decl.inputs[1].span,
+                param_num: 2,
+                expected_ty: tcx.types.isize,
+                found_ty: argc_arg,
+            });
+        }
+    }
+
+    // third arg is `*const *const u8`
+    if let Some(&argv_arg) = inputs.get(2) {
+        let mut argv_is_okay = false;
+        if let ty::RawPtr(outer_ptr) = argv_arg.kind() {
+            if outer_ptr.mutbl.is_not() {
+                if let ty::RawPtr(inner_ptr) = outer_ptr.ty.kind() {
+                    if inner_ptr.mutbl.is_not() && inner_ptr.ty == tcx.types.u8 {
+                        argv_is_okay = true;
+                    }
+                }
+            }
+        }
+
+        if !argv_is_okay {
+            let inner_ptr_ty =
+                tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 });
+            let expected_ty =
+                tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty });
+            tcx.sess.emit_err(LangStartIncorrectParam {
+                param_span: decl.inputs[2].span,
+                param_num: 3,
+                expected_ty,
+                found_ty: argv_arg,
+            });
+        }
+    }
+
+    // fourth arg is `sigpipe: u8`
+    if let Some(&sigpipe_arg) = inputs.get(3) {
+        if sigpipe_arg != tcx.types.u8 {
+            tcx.sess.emit_err(LangStartIncorrectParam {
+                param_span: decl.inputs[3].span,
+                param_num: 4,
+                expected_ty: tcx.types.u8,
+                found_ty: sigpipe_arg,
+            });
+        }
+    }
+
+    // output type is isize
+    if fn_sig.output() != tcx.types.isize {
+        tcx.sess.emit_err(LangStartIncorrectRetTy {
+            ret_span: decl.output.span(),
+            expected_ty: tcx.types.isize,
+            found_ty: fn_sig.output(),
+        });
+    }
+}
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 507272fdec5..5b4fd5e4a52 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -172,3 +172,36 @@ impl AddToDiagnostic for TypeMismatchFruTypo {
         );
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_lang_start_incorrect_number_params)]
+#[note(hir_typeck_lang_start_incorrect_number_params_note_expected_count)]
+#[note(hir_typeck_lang_start_expected_sig_note)]
+pub struct LangStartIncorrectNumberArgs {
+    #[primary_span]
+    pub params_span: Span,
+    pub found_param_count: usize,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_lang_start_incorrect_param)]
+pub struct LangStartIncorrectParam<'tcx> {
+    #[primary_span]
+    #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
+    pub param_span: Span,
+
+    pub param_num: usize,
+    pub expected_ty: Ty<'tcx>,
+    pub found_ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_lang_start_incorrect_ret_ty)]
+pub struct LangStartIncorrectRetTy<'tcx> {
+    #[primary_span]
+    #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
+    pub ret_span: Span,
+
+    pub expected_ty: Ty<'tcx>,
+    pub found_ty: Ty<'tcx>,
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 080ae6b9466..533a3c768eb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1782,9 +1782,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             // like when you have two references but one is `usize` and the other
                             // is `f32`. In those cases we still want to show the `note`. If the
                             // value from `ef` is `Infer(_)`, then we ignore it.
-                            if !ef.expected.is_ty_infer() {
+                            if !ef.expected.is_ty_or_numeric_infer() {
                                 ef.expected != values.expected
-                            } else if !ef.found.is_ty_infer() {
+                            } else if !ef.found.is_ty_or_numeric_infer() {
                                 ef.found != values.found
                             } else {
                                 false
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index a4c36b4c9cd..b8c843a8a5a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -78,7 +78,7 @@ impl InferenceDiagnosticsData {
     }
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
-        if in_type.is_ty_infer() {
+        if in_type.is_ty_or_numeric_infer() {
             ""
         } else if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
@@ -195,12 +195,12 @@ fn ty_to_string<'tcx>(
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
         (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
         (_, Some(def_id))
-            if ty.is_ty_infer()
+            if ty.is_ty_or_numeric_infer()
                 && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
         {
             "Vec<_>".to_string()
         }
-        _ if ty.is_ty_infer() => "/* Type */".to_string(),
+        _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
         // FIXME: The same thing for closures, but this only works when the closure
         // does not capture anything.
         //
@@ -680,7 +680,7 @@ impl<'tcx> InferSourceKind<'tcx> {
             | InferSourceKind::ClosureReturn { ty, .. } => {
                 if ty.is_closure() {
                     ("closure", closure_as_fn_str(infcx, ty))
-                } else if !ty.is_ty_infer() {
+                } else if !ty.is_ty_or_numeric_infer() {
                     ("normal", ty_to_string(infcx, ty, None))
                 } else {
                     ("other", String::new())
@@ -813,7 +813,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
         self.attempt += 1;
         if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
             && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
-            && ty.is_ty_infer()
+            && ty.is_ty_or_numeric_infer()
         {
             // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
             // `let x: _ = iter.collect();`, as this is a very common case.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index c8085e91dfa..50c40206d80 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -823,23 +823,26 @@ pub fn create_global_ctxt<'tcx>(
                 lint_store,
                 arena,
                 hir_arena,
-                untracked_resolutions,
                 untracked,
-                krate,
                 dep_graph,
                 queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
                 queries.as_dyn(),
                 rustc_query_impl::query_callbacks(arena),
-                crate_name,
-                outputs,
             )
         })
     });
 
     let mut qcx = QueryContext { gcx };
     qcx.enter(|tcx| {
-        tcx.feed_unit_query()
-            .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering)))
+        let feed = tcx.feed_unit_query();
+        feed.resolver_for_lowering(
+            tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))),
+        );
+        feed.resolutions(tcx.arena.alloc(untracked_resolutions));
+        feed.output_filenames(tcx.arena.alloc(std::sync::Arc::new(outputs)));
+        feed.features_query(sess.features_untracked());
+        let feed = tcx.feed_local_crate();
+        feed.crate_name(crate_name);
     });
     qcx
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index a3b9891ee64..07b28cc86ce 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -748,6 +748,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(link_only, true);
     tracked!(llvm_plugins, vec![String::from("plugin_name")]);
     tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
+    tracked!(log_backtrace, Some("filter".to_string()));
     tracked!(maximal_hir_to_mir_coverage, true);
     tracked!(merge_functions, Some(MergeFunctions::Disabled));
     tracked!(mir_emit_retag, true);
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 70c999811a5..e9eb14ea188 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -11,7 +11,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
-    if !tcx.sess.features_untracked().enabled(sym::lint_reasons) {
+    if !tcx.features().enabled(sym::lint_reasons) {
         return;
     }
 
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 28317d6cea0..6cdf5097083 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4033,10 +4033,10 @@ declare_lint! {
     ///
     /// This can be used to implement an unsound API if used incorrectly.
     pub IMPLIED_BOUNDS_ENTAILMENT,
-    Warn,
+    Deny,
     "impl method assumes more implied bounds than its corresponding trait method",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #105572 <https://github.com/rust-lang/rust/issues/105572>",
-        reason: FutureIncompatibilityReason::FutureReleaseError,
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
 }
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index 3c50827c1ab..7f955b0a750 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 tracing = "0.1.28"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 tracing-tree = "0.2.0"
+tracing-core = "0.1.28"
 
 [dev-dependencies]
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index 4cac88aff64..fc1cabd2de9 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -45,16 +45,34 @@
 use std::env::{self, VarError};
 use std::fmt::{self, Display};
 use std::io::{self, IsTerminal};
+use tracing_core::{Event, Subscriber};
 use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter};
+use tracing_subscriber::fmt::{
+    format::{self, FormatEvent, FormatFields},
+    FmtContext,
+};
 use tracing_subscriber::layer::SubscriberExt;
 
 pub fn init_rustc_env_logger() -> Result<(), Error> {
-    init_env_logger("RUSTC_LOG")
+    init_rustc_env_logger_with_backtrace_option(&None)
+}
+
+pub fn init_rustc_env_logger_with_backtrace_option(
+    backtrace_target: &Option<String>,
+) -> Result<(), Error> {
+    init_env_logger_with_backtrace_option("RUSTC_LOG", backtrace_target)
 }
 
 /// In contrast to `init_rustc_env_logger` this allows you to choose an env var
 /// other than `RUSTC_LOG`.
 pub fn init_env_logger(env: &str) -> Result<(), Error> {
+    init_env_logger_with_backtrace_option(env, &None)
+}
+
+pub fn init_env_logger_with_backtrace_option(
+    env: &str,
+    backtrace_target: &Option<String>,
+) -> Result<(), Error> {
     let filter = match env::var(env) {
         Ok(env) => EnvFilter::new(env),
         _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)),
@@ -88,11 +106,47 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> {
     let layer = layer.with_thread_ids(true).with_thread_names(true);
 
     let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
-    tracing::subscriber::set_global_default(subscriber).unwrap();
+    match backtrace_target {
+        Some(str) => {
+            let fmt_layer = tracing_subscriber::fmt::layer()
+                .with_writer(io::stderr)
+                .without_time()
+                .event_format(BacktraceFormatter { backtrace_target: str.to_string() });
+            let subscriber = subscriber.with(fmt_layer);
+            tracing::subscriber::set_global_default(subscriber).unwrap();
+        }
+        None => {
+            tracing::subscriber::set_global_default(subscriber).unwrap();
+        }
+    };
 
     Ok(())
 }
 
+struct BacktraceFormatter {
+    backtrace_target: String,
+}
+
+impl<S, N> FormatEvent<S, N> for BacktraceFormatter
+where
+    S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
+    N: for<'a> FormatFields<'a> + 'static,
+{
+    fn format_event(
+        &self,
+        _ctx: &FmtContext<'_, S, N>,
+        mut writer: format::Writer<'_>,
+        event: &Event<'_>,
+    ) -> fmt::Result {
+        let target = event.metadata().target();
+        if !target.contains(&self.backtrace_target) {
+            return Ok(());
+        }
+        let backtrace = std::backtrace::Backtrace::capture();
+        writeln!(writer, "stack backtrace: \n{:?}", backtrace)
+    }
+}
+
 pub fn stdout_isatty() -> bool {
     io::stdout().is_terminal()
 }
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 75282f958b5..f816d614500 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -30,7 +30,12 @@ macro_rules! arena_types {
             [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
             [decode] borrowck_result:
                 rustc_middle::mir::BorrowCheckResult<'tcx>,
-            [] resolver: rustc_data_structures::steal::Steal<rustc_middle::ty::ResolverAstLowering>,
+            [] resolver: rustc_data_structures::steal::Steal<(
+                rustc_middle::ty::ResolverAstLowering,
+                rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
+            )>,
+            [] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
+            [] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
             [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
             [decode] code_region: rustc_middle::mir::coverage::CodeRegion,
             [] const_allocs: rustc_middle::mir::interpret::Allocation,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 076ce1bdb34..86655915736 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -27,12 +27,12 @@ rustc_queries! {
     }
 
     query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
-        eval_always
+        feedable
         no_hash
         desc { "getting the resolver outputs" }
     }
 
-    query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> {
+    query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
         feedable
         no_hash
         desc { "getting the resolver for lowering" }
@@ -1673,7 +1673,7 @@ rustc_queries! {
 
     /// Gets the name of the crate.
     query crate_name(_: CrateNum) -> Symbol {
-        eval_always
+        feedable
         desc { "fetching what a crate is named" }
         separate_provide_extern
     }
@@ -1857,7 +1857,7 @@ rustc_queries! {
     /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt`
     /// has been destroyed.
     query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> {
-        eval_always
+        feedable
         desc { "getting output filenames" }
     }
 
@@ -2041,7 +2041,7 @@ rustc_queries! {
     }
 
     query features_query(_: ()) -> &'tcx rustc_feature::Features {
-        eval_always
+        feedable
         desc { "looking up enabled feature gates" }
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 5de414077a2..63f31e5a11f 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -51,7 +51,7 @@ use rustc_macros::HashStable;
 use rustc_query_system::dep_graph::DepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
-use rustc_session::config::{CrateType, OutputFilenames};
+use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
 use rustc_session::Limit;
@@ -74,7 +74,6 @@ use std::hash::{Hash, Hasher};
 use std::iter;
 use std::mem;
 use std::ops::{Bound, Deref};
-use std::sync::Arc;
 
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
@@ -363,6 +362,9 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
         TyCtxtFeed { tcx: self, key: () }
     }
+    pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
+        TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
+    }
 }
 
 impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
@@ -428,11 +430,6 @@ pub struct GlobalCtxt<'tcx> {
     pub consts: CommonConsts<'tcx>,
 
     untracked: Untracked,
-    /// Output of the resolver.
-    pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
-    /// The entire crate as AST. This field serves as the input for the hir_crate query,
-    /// which lowers it from AST to HIR. It must not be read or used by anything else.
-    pub untracked_crate: Steal<Lrc<ast::Crate>>,
 
     /// This provides access to the incremental compilation on-disk cache for query results.
     /// Do not access this directly. It is only meant to be used by
@@ -457,17 +454,11 @@ pub struct GlobalCtxt<'tcx> {
     /// Merge this with `selection_cache`?
     pub evaluation_cache: traits::EvaluationCache<'tcx>,
 
-    /// The definite name of the current crate after taking into account
-    /// attributes, commandline parameters, etc.
-    crate_name: Symbol,
-
     /// Data layout specification for the current target.
     pub data_layout: TargetDataLayout,
 
     /// Stores memory for globals (statics/consts).
     pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
-
-    output_filenames: Arc<OutputFilenames>,
 }
 
 impl<'tcx> TyCtxt<'tcx> {
@@ -592,15 +583,11 @@ impl<'tcx> TyCtxt<'tcx> {
         lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
-        untracked_resolutions: ty::ResolverGlobalCtxt,
         untracked: Untracked,
-        krate: Lrc<ast::Crate>,
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        crate_name: Symbol,
-        output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
@@ -622,8 +609,6 @@ impl<'tcx> TyCtxt<'tcx> {
             lifetimes: common_lifetimes,
             consts: common_consts,
             untracked,
-            untracked_resolutions,
-            untracked_crate: Steal::new(krate),
             on_disk_cache,
             queries,
             query_caches: query::QueryCaches::default(),
@@ -632,10 +617,8 @@ impl<'tcx> TyCtxt<'tcx> {
             pred_rcache: Default::default(),
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
-            crate_name,
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
-            output_filenames: Arc::new(output_filenames),
         }
     }
 
@@ -810,7 +793,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // statements within the query system and we'd run into endless
         // recursion otherwise.
         let (crate_name, stable_crate_id) = if def_id.is_local() {
-            (self.crate_name, self.sess.local_stable_crate_id())
+            (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
         } else {
             let cstore = &*self.untracked.cstore;
             (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
@@ -2407,13 +2390,8 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
     providers.module_reexports =
         |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
-    providers.crate_name = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        tcx.crate_name
-    };
     providers.maybe_unused_trait_imports =
         |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
     providers.maybe_unused_extern_crates =
@@ -2424,8 +2402,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
 
     providers.extern_mod_stmt_cnum =
         |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
-    providers.output_filenames = |tcx, ()| &tcx.output_filenames;
-    providers.features_query = |tcx, ()| tcx.sess.features_untracked();
     providers.is_panic_runtime = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
         tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index f7e4c821569..bd5b04d5b2b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1686,7 +1686,7 @@ impl<'tcx> Ty<'tcx> {
     }
 
     #[inline]
-    pub fn is_ty_infer(self) -> bool {
+    pub fn is_ty_or_numeric_infer(self) -> bool {
         matches!(self.kind(), Infer(_))
     }
 
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 0c33e5bda1a..2dec58ea82a 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -202,7 +202,7 @@ impl<'tcx> GenericArg<'tcx> {
     pub fn is_non_region_infer(self) -> bool {
         match self.unpack() {
             GenericArgKind::Lifetime(_) => false,
-            GenericArgKind::Type(ty) => ty.is_ty_infer(),
+            GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(),
             GenericArgKind::Const(ct) => ct.is_ct_infer(),
         }
     }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c59c06ac31e..f9f9799d3e4 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -82,6 +82,7 @@ impl CheckAttrVisitor<'_> {
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
             let attr_is_valid = match attr.name_or_empty() {
+                sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
                 sym::inline => self.check_inline(hir_id, attr, span, target),
                 sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
                 sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
@@ -241,6 +242,16 @@ impl CheckAttrVisitor<'_> {
         );
     }
 
+    /// Checks if `#[do_not_recommend]` is applied on a trait impl.
+    fn check_do_not_recommend(&self, attr_span: Span, target: Target) -> bool {
+        if let Target::Impl = target {
+            true
+        } else {
+            self.tcx.sess.emit_err(errors::IncorrectDoNotRecommendLocation { span: attr_span });
+            false
+        }
+    }
+
     /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
     fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
         match target {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index c6cd69add28..9c6519ea4bb 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -14,6 +14,13 @@ use rustc_span::{Span, Symbol, DUMMY_SP};
 
 use crate::lang_items::Duplicate;
 
+#[derive(Diagnostic)]
+#[diag(passes_incorrect_do_not_recommend_location)]
+pub struct IncorrectDoNotRecommendLocation {
+    #[primary_span]
+    pub span: Span,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(passes_outer_crate_level_attr)]
 pub struct OuterCrateLevelAttr;
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 1a852de8eed..fb2aebbd18a 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -167,7 +167,7 @@ impl<'a> Resolver<'a> {
                 );
                 err.emit();
             } else if let Some((span, msg, sugg, appl)) = suggestion {
-                err.span_suggestion(span, msg, sugg, appl);
+                err.span_suggestion_verbose(span, msg, sugg, appl);
                 err.emit();
             } else if let [segment] = path.as_slice() && is_call {
                 err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d92f5a7c05e..d92b046d0b9 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2065,7 +2065,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         path: &[Segment],
     ) -> Option<(Span, &'static str, String, Applicability)> {
         let (ident, span) = match path {
-            [segment] if !segment.has_generic_args && segment.ident.name != kw::SelfUpper => {
+            [segment]
+                if !segment.has_generic_args
+                    && segment.ident.name != kw::SelfUpper
+                    && segment.ident.name != kw::Dyn =>
+            {
                 (segment.ident.to_string(), segment.ident.span)
             }
             _ => return None,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b062b43873b..7b5fd6cc2a8 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1411,6 +1411,8 @@ options! {
         "what location details should be tracked when using caller_location, either \
         `none`, or a comma separated list of location details, for which \
         valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
+    log_backtrace: Option<String> = (None, parse_opt_string, [TRACKED],
+        "add a backtrace along with logging"),
     ls: bool = (false, parse_bool, [UNTRACKED],
         "list the symbols defined by a library crate (default: no)"),
     macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 20bede22c34..0c7ffb056cc 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2252,8 +2252,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     Ok(None) => {
                         let ambiguities =
                             ambiguity::recompute_applicable_impls(self.infcx, &obligation);
-                        let has_non_region_infer =
-                            trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
+                        let has_non_region_infer = trait_ref
+                            .skip_binder()
+                            .substs
+                            .types()
+                            .any(|t| !t.is_ty_or_numeric_infer());
                         // It doesn't make sense to talk about applicable impls if there are more
                         // than a handful of them.
                         if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 5f8c777f32a..d1b6d470e86 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1221,7 +1221,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
     ) {
         let ast_attrs = self.tcx.hir().attrs(hir_id);
         if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
-            if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) {
+            if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) {
                 return;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 0710ac0bb0a..751c262673b 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -472,7 +472,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe
 
 fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) {
     // Check for the feature
-    if !cx.tcx.sess.features_untracked().lint_reasons {
+    if !cx.tcx.features().lint_reasons {
         return;
     }
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
index 638e4a54849..efdd56dd47d 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr
@@ -17,9 +17,12 @@ error[E0412]: cannot find type `VAL` in this scope
   --> $DIR/ice-6252.rs:10:63
    |
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   |          -                                                    ^^^ not found in this scope
-   |          |
-   |          help: you might be missing a type parameter: `, VAL`
+   |                                                               ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<N, M, VAL> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+   |          +++++
 
 error[E0046]: not all trait items implemented, missing: `VAL`
   --> $DIR/ice-6252.rs:10:1
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index a7da8f89aa3..1af77d1a25b 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -15,7 +15,7 @@ pub trait Copy {}
 pub unsafe trait Freeze {}
 
 #[lang = "start"]
-fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
     0
 }
 
diff --git a/tests/run-make-fulldeps/target-specs/foo.rs b/tests/run-make-fulldeps/target-specs/foo.rs
index d576a1dd281..22939e87912 100644
--- a/tests/run-make-fulldeps/target-specs/foo.rs
+++ b/tests/run-make-fulldeps/target-specs/foo.rs
@@ -11,7 +11,7 @@ trait Sized {}
 auto trait Freeze {}
 
 #[lang = "start"]
-fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
     0
 }
 
diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout
index 43f30f3d6e8..4bdecdc1b79 100644
--- a/tests/rustdoc-ui/z-help.stdout
+++ b/tests/rustdoc-ui/z-help.stdout
@@ -76,6 +76,7 @@
     -Z                            llvm-plugins=val -- a list LLVM plugins to enable (space separated)
     -Z                         llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
     -Z                         location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
+    -Z                           log-backtrace=val -- add a backtrace along with logging
     -Z                                      ls=val -- list the symbols defined by a library crate (default: no)
     -Z                         macro-backtrace=val -- show macro backtraces (default: no)
     -Z             maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed
new file mode 100644
index 00000000000..23f71520040
--- /dev/null
+++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+trait Trait<A> {}
+
+trait Assoc {
+    type Ty;
+}
+
+impl<A> Assoc for dyn Trait<A> {
+    type Ty = i32;
+}
+
+fn main() {
+    let _x: <dyn Trait<i32> as Assoc>::Ty; //~ ERROR ambiguous associated type
+}
diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs
new file mode 100644
index 00000000000..9c26e339a44
--- /dev/null
+++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+trait Trait<A> {}
+
+trait Assoc {
+    type Ty;
+}
+
+impl<A> Assoc for dyn Trait<A> {
+    type Ty = i32;
+}
+
+fn main() {
+    let _x: <dyn Trait<i32>>::Ty; //~ ERROR ambiguous associated type
+}
diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr
new file mode 100644
index 00000000000..97088b79fd6
--- /dev/null
+++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-associated-type-with-generics.rs:13:13
+   |
+LL |     let _x: <dyn Trait<i32>>::Ty;
+   |             ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<dyn Trait<i32> as Assoc>::Ty`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
index bf4bd634cf1..d0c17062076 100644
--- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
+++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr
@@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/associated-item-duplicate-names-3.rs:18:12
    |
 LL |     let x: Baz::Bar = 5;
-   |            ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar`
+   |            ^^^^^^^^ help: use the fully-qualified path: `<Baz as Foo>::Bar`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index 289911779ff..00856b55df5 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -2,31 +2,46 @@ error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:6:36
    |
 LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
-   |                                    ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
+   |                                    ^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
+   |
+LL | fn get<T:Get,U:Get>(x: T, y: U) -> <Example as Get>::Value {}
+   |                                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:20:17
    |
 LL | trait Foo where Foo::Assoc: Bar {
-   |                 ^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Foo>::Assoc`
+   |                 ^^^^^^^^^^ help: use the fully-qualified path: `<Self as Foo>::Assoc`
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:25:10
    |
 LL | type X = std::ops::Deref::Target;
-   |          ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Deref>::Target`
+   |          ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path
+   |
+LL | type X = <Example as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:11:23
    |
 LL |     fn grab(&self) -> Grab::Value;
-   |                       ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
+   |                       ^^^^^^^^^^^ help: use the fully-qualified path: `<Self as Grab>::Value`
 
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:14:22
    |
 LL |     fn get(&self) -> Get::Value;
-   |                      ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as Get>::Value`
+   |                      ^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
+   |
+LL |     fn get(&self) -> <Example as Get>::Value;
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/attributes/log-backtrace.rs b/tests/ui/attributes/log-backtrace.rs
new file mode 100644
index 00000000000..3979d2001fc
--- /dev/null
+++ b/tests/ui/attributes/log-backtrace.rs
@@ -0,0 +1,9 @@
+// run-pass
+//
+// This test makes sure that log-backtrace option doesn't give a compilation error.
+//
+// dont-check-compiler-stdout
+// dont-check-compiler-stderr
+// rustc-env:RUSTC_LOG=info
+// compile-flags: -Zlog-backtrace=rustc_metadata::creader
+fn main() {}
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
index 492316f0027..592aa4369ce 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/builtin-superkinds-double-superkind.rs:6:24
+  --> $DIR/builtin-superkinds-double-superkind.rs:6:32
    |
 LL | impl <T: Sync+'static> Foo for (T,) { }
-   |                        ^^^ `T` cannot be sent between threads safely
+   |                                ^^^^ `T` cannot be sent between threads safely
    |
    = note: required because it appears within the type `(T,)`
 note: required by a bound in `Foo`
@@ -16,10 +16,10 @@ LL | impl <T: Sync+'static + std::marker::Send> Foo for (T,) { }
    |                       +++++++++++++++++++
 
 error[E0277]: `T` cannot be shared between threads safely
-  --> $DIR/builtin-superkinds-double-superkind.rs:9:16
+  --> $DIR/builtin-superkinds-double-superkind.rs:9:24
    |
 LL | impl <T: Send> Foo for (T,T) { }
-   |                ^^^ `T` cannot be shared between threads safely
+   |                        ^^^^^ `T` cannot be shared between threads safely
    |
    = note: required because it appears within the type `(T, T)`
 note: required by a bound in `Foo`
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
index a46e4b2337c..f9d548bb8fb 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/builtin-superkinds-in-metadata.rs:13:23
+  --> $DIR/builtin-superkinds-in-metadata.rs:13:56
    |
 LL | impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely
+   |                                                        ^^^^ `T` cannot be sent between threads safely
    |
 note: required because it appears within the type `X<T>`
   --> $DIR/builtin-superkinds-in-metadata.rs:9:8
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr
index 9db9cbfdb91..8b19170b0f1 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `Rc<i8>` cannot be sent between threads safely
-  --> $DIR/builtin-superkinds-simple.rs:6:6
+  --> $DIR/builtin-superkinds-simple.rs:6:14
    |
 LL | impl Foo for std::rc::Rc<i8> { }
-   |      ^^^ `Rc<i8>` cannot be sent between threads safely
+   |              ^^^^^^^^^^^^^^^ `Rc<i8>` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `Rc<i8>`
 note: required by a bound in `Foo`
diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
index 3ec0b907d0c..0cfea72d5f1 100644
--- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
+++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/builtin-superkinds-typaram-not-send.rs:5:24
+  --> $DIR/builtin-superkinds-typaram-not-send.rs:5:32
    |
 LL | impl <T: Sync+'static> Foo for T { }
-   |                        ^^^ `T` cannot be sent between threads safely
+   |                                ^ `T` cannot be sent between threads safely
    |
 note: required by a bound in `Foo`
   --> $DIR/builtin-superkinds-typaram-not-send.rs:3:13
diff --git a/tests/ui/chalkify/impl_wf.stderr b/tests/ui/chalkify/impl_wf.stderr
index a142459bcb4..84c32fa3771 100644
--- a/tests/ui/chalkify/impl_wf.stderr
+++ b/tests/ui/chalkify/impl_wf.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/impl_wf.rs:11:6
+  --> $DIR/impl_wf.rs:11:14
    |
 LL | impl Foo for str { }
-   |      ^^^ doesn't have a size known at compile-time
+   |              ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `Foo`
@@ -12,10 +12,10 @@ LL | trait Foo: Sized { }
    |            ^^^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `f32: Foo` is not satisfied
-  --> $DIR/impl_wf.rs:22:6
+  --> $DIR/impl_wf.rs:22:19
    |
 LL | impl Baz<f32> for f32 { }
-   |      ^^^^^^^^ the trait `Foo` is not implemented for `f32`
+   |                   ^^^ the trait `Foo` is not implemented for `f32`
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `Baz`
diff --git a/tests/ui/coherence/coherence-overlap-trait-alias.stderr b/tests/ui/coherence/coherence-overlap-trait-alias.stderr
index e324c1e799f..668b8319b38 100644
--- a/tests/ui/coherence/coherence-overlap-trait-alias.stderr
+++ b/tests/ui/coherence/coherence-overlap-trait-alias.stderr
@@ -1,8 +1,8 @@
 error[E0283]: type annotations needed: cannot satisfy `u32: C`
-  --> $DIR/coherence-overlap-trait-alias.rs:15:6
+  --> $DIR/coherence-overlap-trait-alias.rs:15:12
    |
 LL | impl C for u32 {}
-   |      ^
+   |            ^^^
    |
 note: multiple `impl`s satisfying `u32: C` found
   --> $DIR/coherence-overlap-trait-alias.rs:14:1
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr
index 21f957ab549..55096e95df7 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr
@@ -61,25 +61,45 @@ error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:1:10
    |
 LL | type A = [u8; 4]::AssocTy;
-   |          ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; 4] as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path
+   |
+LL | type A = <[u8; 4] as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:5:10
    |
 LL | type B = [u8]::AssocTy;
-   |          ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8] as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path
+   |
+LL | type B = <[u8] as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:9:10
    |
 LL | type C = (u8)::AssocTy;
-   |          ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL | type C = <u8 as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:13:10
    |
 LL | type D = (u8, u8)::AssocTy;
-   |          ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path
+   |
+LL | type D = <(u8, u8) as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
   --> $DIR/bad-assoc-ty.rs:17:10
@@ -91,13 +111,23 @@ error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:21:19
    |
 LL | type F = &'static (u8)::AssocTy;
-   |                   ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+   |                   ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL | type F = &'static <u8 as Example>::AssocTy;
+   |                   ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:27:10
    |
 LL | type G = dyn 'static + (Send)::AssocTy;
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Send + 'static) as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path
+   |
+LL | type G = <(dyn Send + 'static) as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/bad-assoc-ty.rs:33:10
@@ -117,24 +147,33 @@ error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:33:10
    |
 LL | type H = Fn(u8) -> (u8)::Output;
-   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as Trait>::Output`
+   |          ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output`
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:39:19
    |
 LL |     ($ty: ty) => ($ty::AssocTy);
-   |                   ^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+   |                   ^^^^^^^^^^^^
 ...
 LL | type J = ty!(u8);
    |          ------- in this macro invocation
    |
    = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL |     ($ty: ty) => (<u8 as Example>::AssocTy);
+   |                   ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:46:10
    |
 LL | type I = ty!()::AssocTy;
-   |          ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<u8 as Trait>::AssocTy`
+   |          ^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL | type I = <u8 as Example>::AssocTy;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/bad-assoc-ty.rs:51:13
diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr
index 8ec94f5a3c0..60e9de90332 100644
--- a/tests/ui/dst/dst-sized-trait-param.stderr
+++ b/tests/ui/dst/dst-sized-trait-param.stderr
@@ -16,10 +16,10 @@ LL | trait Foo<T: ?Sized> : Sized { fn take(self, x: &T) { } } // Note: T is siz
    |            ++++++++
 
 error[E0277]: the size for values of type `[usize]` cannot be known at compilation time
-  --> $DIR/dst-sized-trait-param.rs:10:6
+  --> $DIR/dst-sized-trait-param.rs:10:21
    |
 LL | impl Foo<isize> for [usize] { }
-   |      ^^^^^^^^^^ doesn't have a size known at compile-time
+   |                     ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[usize]`
 note: required by a bound in `Foo`
diff --git a/tests/ui/error-codes/E0223.rs b/tests/ui/error-codes/E0223.rs
index 6031b682d72..2fe252de256 100644
--- a/tests/ui/error-codes/E0223.rs
+++ b/tests/ui/error-codes/E0223.rs
@@ -1,4 +1,8 @@
 trait MyTrait { type X; }
+struct MyStruct;
+impl MyTrait for MyStruct {
+    type X = ();
+}
 
 fn main() {
     let foo: MyTrait::X;
diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr
index 726f39e11f1..42945e42f6e 100644
--- a/tests/ui/error-codes/E0223.stderr
+++ b/tests/ui/error-codes/E0223.stderr
@@ -1,8 +1,8 @@
 error[E0223]: ambiguous associated type
-  --> $DIR/E0223.rs:4:14
+  --> $DIR/E0223.rs:8:14
    |
 LL |     let foo: MyTrait::X;
-   |              ^^^^^^^^^^ help: use fully-qualified syntax: `<Type as MyTrait>::X`
+   |              ^^^^^^^^^^ help: use the fully-qualified path: `<MyStruct as MyTrait>::X`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/error-codes/E0308-2.stderr b/tests/ui/error-codes/E0308-2.stderr
index de54a417253..3a8a81a73a6 100644
--- a/tests/ui/error-codes/E0308-2.stderr
+++ b/tests/ui/error-codes/E0308-2.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/E0308-2.rs:9:6
+  --> $DIR/E0308-2.rs:9:13
    |
 LL | impl Eq for &dyn DynEq {}
-   |      ^^ lifetime mismatch
+   |             ^^^^^^^^^^ lifetime mismatch
    |
    = note: expected trait `<&dyn DynEq as PartialEq>`
               found trait `<&(dyn DynEq + 'static) as PartialEq>`
diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr
index 26bdf460f5e..9d4ea01152c 100644
--- a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr
+++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr
@@ -2,9 +2,12 @@ error[E0412]: cannot find type `T` in this scope
   --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13
    |
 LL | impl Struct<T>
-   |     -       ^ not found in this scope
-   |     |
-   |     help: you might be missing a type parameter: `<T>`
+   |             ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<T> Struct<T>
+   |     +++
 
 error[E0412]: cannot find type `T` in this scope
   --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5
diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs
index fd0986d7c0a..b3ff2ce5a7b 100644
--- a/tests/ui/impl-trait/impl_trait_projections.rs
+++ b/tests/ui/impl-trait/impl_trait_projections.rs
@@ -11,7 +11,7 @@ fn path_parametrized_type_is_allowed() -> option::Option<impl Debug> {
 
 fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
 //~^ ERROR `impl Trait` is not allowed in path parameters
-//~^^ ERROR ambiguous associated type
+//~| ERROR `impl Trait` is not allowed in path parameters
     x.next().unwrap()
 }
 
diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr
index 82d2422c407..4deb24731bc 100644
--- a/tests/ui/impl-trait/impl_trait_projections.stderr
+++ b/tests/ui/impl-trait/impl_trait_projections.stderr
@@ -22,13 +22,12 @@ error[E0667]: `impl Trait` is not allowed in path parameters
 LL |     -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
    |                             ^^^^^^^^^^
 
-error[E0223]: ambiguous associated type
-  --> $DIR/impl_trait_projections.rs:12:50
+error[E0667]: `impl Trait` is not allowed in path parameters
+  --> $DIR/impl_trait_projections.rs:12:51
    |
 LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
-   |                                                  ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<impl Iterator as Trait>::Item`
+   |                                                   ^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0223, E0667.
-For more information about an error, try `rustc --explain E0223`.
+For more information about this error, try `rustc --explain E0667`.
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
index 0ac31c642eb..ebe07027d2f 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr
@@ -1,8 +1,8 @@
 error: impl method assumes more implied bounds than the corresponding trait method
-  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:5
+  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31
    |
 LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()`
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572>
@@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)]
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: impl method assumes more implied bounds than the corresponding trait method
+  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31
+   |
+LL |     fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str {
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572>
+note: the lint level is defined here
+  --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:1:9
+   |
+LL | #![deny(implied_bounds_entailment)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
index 0dfa8167a99..43d3e058ffe 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
@@ -1,8 +1,8 @@
 error: impl method assumes more implied bounds than the corresponding trait method
-  --> $DIR/impl-implied-bounds-compatibility.rs:14:5
+  --> $DIR/impl-implied-bounds-compatibility.rs:14:35
    |
 LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>`
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572>
@@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)]
 
 error: aborting due to previous error
 
+Future incompatibility report: Future breakage diagnostic:
+error: impl method assumes more implied bounds than the corresponding trait method
+  --> $DIR/impl-implied-bounds-compatibility.rs:14:35
+   |
+LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572>
+note: the lint level is defined here
+  --> $DIR/impl-implied-bounds-compatibility.rs:1:9
+   |
+LL | #![deny(implied_bounds_entailment)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr
index 3a10a1ab11a..3a9f49ef167 100644
--- a/tests/ui/issues/issue-23073.stderr
+++ b/tests/ui/issues/issue-23073.stderr
@@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-23073.rs:6:17
    |
 LL |     type FooT = <<Self as Bar>::Foo>::T;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<Self as Bar>::Foo as Trait>::T`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `T` implemented for `<Self as Bar>::Foo`, you could use the fully-qualified path
+   |
+LL |     type FooT = <<Self as Bar>::Foo as Example>::T;
+   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-58712.stderr b/tests/ui/issues/issue-58712.stderr
index 87c16aa993b..f4bd4d1e826 100644
--- a/tests/ui/issues/issue-58712.stderr
+++ b/tests/ui/issues/issue-58712.stderr
@@ -2,9 +2,12 @@ error[E0412]: cannot find type `DeviceId` in this scope
   --> $DIR/issue-58712.rs:6:20
    |
 LL | impl<H> AddrVec<H, DeviceId> {
-   |       -            ^^^^^^^^ not found in this scope
-   |       |
-   |       help: you might be missing a type parameter: `, DeviceId`
+   |                    ^^^^^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<H, DeviceId> AddrVec<H, DeviceId> {
+   |       ++++++++++
 
 error[E0412]: cannot find type `DeviceId` in this scope
   --> $DIR/issue-58712.rs:8:29
diff --git a/tests/ui/issues/issue-65230.stderr b/tests/ui/issues/issue-65230.stderr
index fcabcdea74f..7ccab889483 100644
--- a/tests/ui/issues/issue-65230.stderr
+++ b/tests/ui/issues/issue-65230.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-65230.rs:8:6
+  --> $DIR/issue-65230.rs:8:13
    |
 LL | impl T1 for &dyn T2 {}
-   |      ^^ lifetime mismatch
+   |             ^^^^^^^ lifetime mismatch
    |
    = note: expected trait `<&dyn T2 as T0>`
               found trait `<&(dyn T2 + 'static) as T0>`
diff --git a/tests/ui/issues/issue-77919.stderr b/tests/ui/issues/issue-77919.stderr
index ca256847b1f..d154bfe0cb5 100644
--- a/tests/ui/issues/issue-77919.stderr
+++ b/tests/ui/issues/issue-77919.stderr
@@ -13,9 +13,12 @@ error[E0412]: cannot find type `VAL` in this scope
   --> $DIR/issue-77919.rs:11:63
    |
 LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
-   |          -                                                    ^^^ not found in this scope
-   |          |
-   |          help: you might be missing a type parameter: `, VAL`
+   |                                                               ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<N, M, VAL> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
+   |          +++++
 
 error[E0046]: not all trait items implemented, missing: `VAL`
   --> $DIR/issue-77919.rs:11:1
diff --git a/tests/ui/issues/issue-78622.stderr b/tests/ui/issues/issue-78622.stderr
index f7d44f21d3b..70daf8a2f1a 100644
--- a/tests/ui/issues/issue-78622.stderr
+++ b/tests/ui/issues/issue-78622.stderr
@@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-78622.rs:5:5
    |
 LL |     S::A::<f> {}
-   |     ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+   |     ^^^^
+   |
+help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path
+   |
+LL |     <S as Example>::A::<f> {}
+   |     ~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr
index 6c5917bdf6e..bfa7459ab4a 100644
--- a/tests/ui/issues/issue-86756.stderr
+++ b/tests/ui/issues/issue-86756.stderr
@@ -9,8 +9,6 @@ LL | trait Foo<T, T = T> {}
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/issue-86756.rs:5:10
    |
-LL | fn eq<A, B>() {
-   |           - help: you might be missing a type parameter: `, dyn`
 LL |     eq::<dyn, Foo>
    |          ^^^ not found in this scope
 
diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr
new file mode 100644
index 00000000000..65c99a93c75
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr
@@ -0,0 +1,8 @@
+error: parameter 2 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:75:38
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                                      ^^ help: change the type from `i8` to `isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr
new file mode 100644
index 00000000000..f0947a9b3e9
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr
@@ -0,0 +1,8 @@
+error: parameter 3 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:89:52
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
+   |                                                    ^^ help: change the type from `u8` to `*const *const u8`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr
new file mode 100644
index 00000000000..08efd5088f9
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr
@@ -0,0 +1,13 @@
+error: parameter 3 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:82:52
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |
+help: change the type from `*const *const usize` to `*const *const u8`
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                                                    ~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr
new file mode 100644
index 00000000000..c20a744661d
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr
@@ -0,0 +1,13 @@
+error: parameter 1 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:61:20
+   |
+LL | fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                    ^^^^^^^^^^^^
+   |
+help: change the type from `fn(i32) -> T` to `fn() -> T`
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                    ~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr
new file mode 100644
index 00000000000..8f967252f49
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr
@@ -0,0 +1,13 @@
+error: parameter 1 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:68:20
+   |
+LL | fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                    ^^^^^^^^^^^
+   |
+help: change the type from `fn() -> u16` to `fn() -> T`
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                    ~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr
new file mode 100644
index 00000000000..deb37b868ea
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr
@@ -0,0 +1,8 @@
+error: parameter 1 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:54:20
+   |
+LL | fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+   |                    ^^^ help: change the type from `u64` to `fn() -> T`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr
new file mode 100644
index 00000000000..004c2a67f62
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr
@@ -0,0 +1,11 @@
+error: incorrect number of parameters for the `start` lang item
+  --> $DIR/start_lang_item_args.rs:15:1
+   |
+LL | fn start<T>() -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `start` lang item should have four parameters, but found 0
+   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
new file mode 100644
index 00000000000..1d8285b5900
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
@@ -0,0 +1,8 @@
+error: the return type of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:29:84
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
+   |                                                                                    ^ help: change the type from `()` to `isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr
new file mode 100644
index 00000000000..e545a750f24
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr
@@ -0,0 +1,11 @@
+error: incorrect number of parameters for the `start` lang item
+  --> $DIR/start_lang_item_args.rs:22:1
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `start` lang item should have four parameters, but found 3
+   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.rs b/tests/ui/lang-items/start_lang_item_args.rs
new file mode 100644
index 00000000000..0dbfba39cb6
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.rs
@@ -0,0 +1,101 @@
+// check-fail
+// revisions: missing_all_args missing_sigpipe_arg missing_ret start_ret too_many_args
+// revisions: main_ty main_args main_ret argc argv_inner_ptr argv sigpipe
+
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "copy"]
+pub trait Copy {}
+#[lang = "sized"]
+pub trait Sized {}
+
+#[cfg(missing_all_args)]
+#[lang = "start"]
+fn start<T>() -> isize {
+    //[missing_all_args]~^ ERROR incorrect number of parameters
+    100
+}
+
+#[cfg(missing_sigpipe_arg)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
+    //[missing_sigpipe_arg]~^ ERROR incorrect number of parameters
+    100
+}
+
+#[cfg(missing_ret)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
+//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect
+
+#[cfg(start_ret)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
+    //[start_ret]~^ ERROR the return type of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(too_many_args)]
+#[lang = "start"]
+fn start<T>(
+    //[too_many_args]~^ ERROR incorrect number of parameters
+    _main: fn() -> T,
+    _argc: isize,
+    _argv: *const *const u8,
+    _sigpipe: u8,
+    _extra_arg: (),
+) -> isize {
+    100
+}
+
+#[cfg(main_ty)]
+#[lang = "start"]
+fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+    //[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(main_args)]
+#[lang = "start"]
+fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+    //[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(main_ret)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
+    //[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(argc)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
+    //[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(argv_inner_ptr)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
+    //[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(argv)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
+    //[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect
+    100
+}
+
+#[cfg(sigpipe)]
+#[lang = "start"]
+fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
+    //[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect
+    100
+}
+
+fn main() {}
diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr
new file mode 100644
index 00000000000..b20ae312801
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr
@@ -0,0 +1,8 @@
+error: parameter 4 of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:96:80
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
+   |                                                                                ^^^ help: change the type from `i64` to `u8`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr
new file mode 100644
index 00000000000..935d5f3c8b4
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr
@@ -0,0 +1,8 @@
+error: the return type of the `start` lang item is incorrect
+  --> $DIR/start_lang_item_args.rs:34:87
+   |
+LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
+   |                                                                                       ^^ help: change the type from `u8` to `isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr
new file mode 100644
index 00000000000..30a7ed18a3d
--- /dev/null
+++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr
@@ -0,0 +1,17 @@
+error: incorrect number of parameters for the `start` lang item
+  --> $DIR/start_lang_item_args.rs:41:1
+   |
+LL | / fn start<T>(
+LL | |
+LL | |     _main: fn() -> T,
+LL | |     _argc: isize,
+...  |
+LL | |     _extra_arg: (),
+LL | | ) -> isize {
+   | |__________^
+   |
+   = note: the `start` lang item should have four parameters, but found 5
+   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr
index 8ed303ca606..a19f4963c23 100644
--- a/tests/ui/lint/bare-trait-objects-path.stderr
+++ b/tests/ui/lint/bare-trait-objects-path.stderr
@@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type
   --> $DIR/bare-trait-objects-path.rs:23:12
    |
 LL |     let _: Dyn::Ty;
-   |            ^^^^^^^ help: use fully-qualified syntax: `<dyn Dyn as Trait>::Ty`
+   |            ^^^^^^^ help: use the fully-qualified path: `<dyn Dyn as Assoc>::Ty`
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/bare-trait-objects-path.rs:14:5
diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr
index 235c89e200a..3cd59d6926e 100644
--- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr
+++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr
@@ -1,8 +1,8 @@
 error[E0283]: type annotations needed: cannot satisfy `&(): Marker`
-  --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:6
+  --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:17
    |
 LL | impl Marker for &'_ () {}
-   |      ^^^^^^
+   |                 ^^^^^^
    |
 note: multiple `impl`s satisfying `&(): Marker` found
   --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1
@@ -13,10 +13,10 @@ LL | impl Marker for &'_ () {}
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed: cannot satisfy `&(): Marker`
-  --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:6
+  --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:17
    |
 LL | impl Marker for &'_ () {}
-   |      ^^^^^^
+   |                 ^^^^^^
    |
 note: multiple `impl`s satisfying `&(): Marker` found
   --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1
diff --git a/tests/ui/marker_trait_attr/region-overlap.stderr b/tests/ui/marker_trait_attr/region-overlap.stderr
index 6631fe987e2..c6497b4669d 100644
--- a/tests/ui/marker_trait_attr/region-overlap.stderr
+++ b/tests/ui/marker_trait_attr/region-overlap.stderr
@@ -1,8 +1,8 @@
 error[E0283]: type annotations needed: cannot satisfy `(&'static (), &'a ()): A`
-  --> $DIR/region-overlap.rs:5:10
+  --> $DIR/region-overlap.rs:5:16
    |
 LL | impl<'a> A for (&'static (), &'a ()) {}
-   |          ^
+   |                ^^^^^^^^^^^^^^^^^^^^^
    |
 note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found
   --> $DIR/region-overlap.rs:5:1
@@ -13,10 +13,10 @@ LL | impl<'a> A for (&'a (), &'static ()) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed: cannot satisfy `(&'a (), &'static ()): A`
-  --> $DIR/region-overlap.rs:6:10
+  --> $DIR/region-overlap.rs:6:16
    |
 LL | impl<'a> A for (&'a (), &'static ()) {}
-   |          ^
+   |                ^^^^^^^^^^^^^^^^^^^^^
    |
 note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found
   --> $DIR/region-overlap.rs:5:1
diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr
index 9218ae9d5da..0cae01bd1e3 100644
--- a/tests/ui/parser/dyn-trait-compatibility.stderr
+++ b/tests/ui/parser/dyn-trait-compatibility.stderr
@@ -26,17 +26,13 @@ error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:5:15
    |
 LL | type A2 = dyn<dyn, dyn>;
-   |        -      ^^^ not found in this scope
-   |        |
-   |        help: you might be missing a type parameter: `<dyn>`
+   |               ^^^ not found in this scope
 
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:5:20
    |
 LL | type A2 = dyn<dyn, dyn>;
-   |        -           ^^^ not found in this scope
-   |        |
-   |        help: you might be missing a type parameter: `<dyn>`
+   |                    ^^^ not found in this scope
 
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:9:11
@@ -48,9 +44,7 @@ error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:9:16
    |
 LL | type A3 = dyn<<dyn as dyn>::dyn>;
-   |        -       ^^^ not found in this scope
-   |        |
-   |        help: you might be missing a type parameter: `<dyn>`
+   |                ^^^ not found in this scope
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/qualified/qualified-path-params-2.stderr b/tests/ui/qualified/qualified-path-params-2.stderr
index 948f21fce4b..b6cf19b8286 100644
--- a/tests/ui/qualified/qualified-path-params-2.stderr
+++ b/tests/ui/qualified/qualified-path-params-2.stderr
@@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/qualified-path-params-2.rs:18:10
    |
 LL | type A = <S as Tr>::A::f<u8>;
-   |          ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<S as Tr>::A as Trait>::f`
+   |          ^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `f` implemented for `<S as Tr>::A`, you could use the fully-qualified path
+   |
+LL | type A = <<S as Tr>::A as Example>::f;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/resolve/issue-103202.stderr b/tests/ui/resolve/issue-103202.stderr
index 880389371ef..d4d141fb06f 100644
--- a/tests/ui/resolve/issue-103202.stderr
+++ b/tests/ui/resolve/issue-103202.stderr
@@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-103202.rs:4:17
    |
 LL |     fn f(self: &S::x) {}
-   |                 ^^^^ help: use fully-qualified syntax: `<S as Trait>::x`
+   |                 ^^^^
+   |
+help: if there were a trait named `Example` with associated type `x` implemented for `S`, you could use the fully-qualified path
+   |
+LL |     fn f(self: &<S as Example>::x) {}
+   |                 ~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs
new file mode 100644
index 00000000000..91863f5e497
--- /dev/null
+++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs
@@ -0,0 +1,45 @@
+#![feature(do_not_recommend)]
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+const CONST: () = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+static Static: () = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+type Type = ();
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+enum Enum {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+extern {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+fn fun() {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+struct Struct {
+}
+
+#[do_not_recommend]
+//~^ `#[do_not_recommend]` can only be placed
+trait Trait {
+}
+
+#[do_not_recommend]
+impl Trait for i32 {
+}
+
+fn main() {
+}
diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr
new file mode 100644
index 00000000000..01ebc23c86e
--- /dev/null
+++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr
@@ -0,0 +1,50 @@
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:3:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:7:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:11:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:15:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:20:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:25:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:30:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: `#[do_not_recommend]` can only be placed on trait implementations
+  --> $DIR/incorrect-locations.rs:35:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs
index b816c4a19da..f0c5c222e78 100644
--- a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs
+++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs
@@ -1,6 +1,9 @@
+trait Foo {
+}
+
 #[do_not_recommend]
 //~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
-trait Foo {
+impl Foo for i32 {
 }
 
 fn main() {
diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
index 425d7e4bca0..1597e5be45f 100644
--- a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
+++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature
-  --> $DIR/unstable-feature.rs:1:1
+  --> $DIR/unstable-feature.rs:4:1
    |
 LL | #[do_not_recommend]
    | ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
index 1f8f312df01..bf12ef1ca77 100644
--- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
+++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `S: ~const Foo` is not satisfied
-  --> $DIR/super-traits-fail.rs:15:12
+  --> $DIR/super-traits-fail.rs:15:20
    |
 LL | impl const Bar for S {}
-   |            ^^^ the trait `~const Foo` is not implemented for `S`
+   |                    ^ the trait `~const Foo` is not implemented for `S`
    |
 note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
-  --> $DIR/super-traits-fail.rs:15:12
+  --> $DIR/super-traits-fail.rs:15:20
    |
 LL | impl const Bar for S {}
-   |            ^^^
+   |                    ^
 note: required by a bound in `Bar`
   --> $DIR/super-traits-fail.rs:8:12
    |
diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr
index fb47f27e022..36372b644d6 100644
--- a/tests/ui/self/self-impl.stderr
+++ b/tests/ui/self/self-impl.stderr
@@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type
   --> $DIR/self-impl.rs:23:16
    |
 LL |         let _: <Self>::Baz = true;
-   |                ^^^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
+   |                ^^^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
 
 error[E0223]: ambiguous associated type
   --> $DIR/self-impl.rs:25:16
    |
 LL |         let _: Self::Baz = true;
-   |                ^^^^^^^^^ help: use fully-qualified syntax: `<Bar as Trait>::Baz`
+   |                ^^^^^^^^^ help: use the fully-qualified path: `<Bar as Foo>::Baz`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr
index 6c7ea007ee0..cb5cc320276 100644
--- a/tests/ui/span/issue-71363.stderr
+++ b/tests/ui/span/issue-71363.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `MyError` doesn't implement `std::fmt::Display`
- --> $DIR/issue-71363.rs:4:6
+ --> $DIR/issue-71363.rs:4:28
   |
 4 | impl std::error::Error for MyError {}
-  |      ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted with the default formatter
+  |                            ^^^^^^^ `MyError` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `MyError`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
@@ -10,10 +10,10 @@ note: required by a bound in `std::error::Error`
  --> $SRC_DIR/core/src/error.rs:LL:COL
 
 error[E0277]: `MyError` doesn't implement `Debug`
- --> $DIR/issue-71363.rs:4:6
+ --> $DIR/issue-71363.rs:4:28
   |
 4 | impl std::error::Error for MyError {}
-  |      ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted using `{:?}`
+  |                            ^^^^^^^ `MyError` cannot be formatted using `{:?}`
   |
   = help: the trait `Debug` is not implemented for `MyError`
   = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr
index be6f04ae62a..505baa23ca3 100644
--- a/tests/ui/specialization/min_specialization/issue-79224.stderr
+++ b/tests/ui/specialization/min_specialization/issue-79224.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:18:17
+  --> $DIR/issue-79224.rs:18:29
    |
 LL | impl<B: ?Sized> Display for Cow<'_, B> {
-   |                 ^^^^^^^ the trait `Clone` is not implemented for `B`
+   |                             ^^^^^^^^^^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr
index abb445214f3..ca5f0b7e21e 100644
--- a/tests/ui/structs/struct-path-associated-type.stderr
+++ b/tests/ui/structs/struct-path-associated-type.stderr
@@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:32:13
    |
 LL |     let s = S::A {};
-   |             ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+   |             ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
 
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:33:13
    |
 LL |     let z = S::A::<u8> {};
-   |             ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+   |             ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
 
 error[E0223]: ambiguous associated type
   --> $DIR/struct-path-associated-type.rs:35:9
    |
 LL |         S::A {} => {}
-   |         ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+   |         ^^^^ help: use the fully-qualified path: `<S as Tr>::A`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed
new file mode 100644
index 00000000000..78e48364bba
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed
@@ -0,0 +1,28 @@
+//run-rustfix
+#![allow(unused)]
+
+struct S;
+impl S {
+    fn foo(&mut self) {
+        let x = |this: &Self, v: i32| {
+            this.bar();
+            this.hel();
+        };
+        self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+        x(self, 1);
+        x(self, 3);
+    }
+    fn bar(&self) {}
+    fn hel(&self) {}
+    fn qux(&mut self) {}
+
+    fn hello(&mut self) {
+        let y = |this: &Self| {
+            this.bar();
+        };
+        self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+        y(self);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs
new file mode 100644
index 00000000000..6d8a9ffc12d
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs
@@ -0,0 +1,28 @@
+//run-rustfix
+#![allow(unused)]
+
+struct S;
+impl S {
+    fn foo(&mut self) {
+        let x = |v: i32| {
+            self.bar();
+            self.hel();
+        };
+        self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+        x(1);
+        x(3);
+    }
+    fn bar(&self) {}
+    fn hel(&self) {}
+    fn qux(&mut self) {}
+
+    fn hello(&mut self) {
+        let y = || {
+            self.bar();
+        };
+        self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable
+        y();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr
new file mode 100644
index 00000000000..bc97d32ebb6
--- /dev/null
+++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr
@@ -0,0 +1,49 @@
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-105761-suggest-self-for-closure.rs:11:9
+   |
+LL |         let x = |v: i32| {
+   |                 -------- immutable borrow occurs here
+LL |             self.bar();
+   |             ---- first borrow occurs due to use of `self` in closure
+...
+LL |         self.qux();
+   |         ^^^^^^^^^^ mutable borrow occurs here
+LL |         x(1);
+   |         - immutable borrow later used here
+   |
+help: try explicitly pass `&Self` into the Closure as an argument
+   |
+LL ~         let x = |this: &Self, v: i32| {
+LL ~             this.bar();
+LL ~             this.hel();
+LL |         };
+LL |         self.qux();
+LL ~         x(self, 1);
+LL ~         x(self, 3);
+   |
+
+error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-105761-suggest-self-for-closure.rs:23:9
+   |
+LL |         let y = || {
+   |                 -- immutable borrow occurs here
+LL |             self.bar();
+   |             ---- first borrow occurs due to use of `self` in closure
+LL |         };
+LL |         self.qux();
+   |         ^^^^^^^^^^ mutable borrow occurs here
+LL |         y();
+   |         - immutable borrow later used here
+   |
+help: try explicitly pass `&Self` into the Closure as an argument
+   |
+LL ~         let y = |this: &Self| {
+LL ~             this.bar();
+LL |         };
+LL |         self.qux();
+LL ~         y(self);
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
index 2bf072ef521..b90ae051fb7 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -21,7 +21,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/let-binding-init-expr-as-ty.rs:2:14
    |
 LL |     let foo: i32::from_be(num);
-   |              ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<i32 as Trait>::from_be`
+   |              ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path
+   |
+LL |     let foo: <i32 as Example>::from_be;
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.stderr b/tests/ui/suggestions/type-not-found-in-adt-field.stderr
index e990fb5ba12..934ba87bbaa 100644
--- a/tests/ui/suggestions/type-not-found-in-adt-field.stderr
+++ b/tests/ui/suggestions/type-not-found-in-adt-field.stderr
@@ -7,10 +7,13 @@ LL |     m: Vec<Someunknownname<String, ()>>,
 error[E0412]: cannot find type `K` in this scope
   --> $DIR/type-not-found-in-adt-field.rs:6:8
    |
-LL | struct OtherStruct {
-   |                   - help: you might be missing a type parameter: `<K>`
 LL |     m: K,
    |        ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct OtherStruct<K> {
+   |                   +++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr
index ec85ada7a8d..da27ba1c58d 100644
--- a/tests/ui/trait-bounds/unsized-bound.stderr
+++ b/tests/ui/trait-bounds/unsized-bound.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `B` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:2:12
+  --> $DIR/unsized-bound.rs:2:30
    |
 LL | impl<A, B> Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {}
-   |         -  ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         -                    ^^^^^^ doesn't have a size known at compile-time
    |         |
    |         this type parameter needs to be `std::marker::Sized`
    |
@@ -38,10 +38,10 @@ LL + impl<A, B> Trait<(A, B)> for (A, B) where B: ?Sized, {}
    |
 
 error[E0277]: the size for values of type `C` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:5:31
+  --> $DIR/unsized-bound.rs:5:52
    |
 LL | impl<A, B: ?Sized, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
-   |                    -          ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    -                               ^^^^^^^^^ doesn't have a size known at compile-time
    |                    |
    |                    this type parameter needs to be `std::marker::Sized`
    |
@@ -92,10 +92,10 @@ LL + impl<A, B, C: ?Sized> Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {}
    |
 
 error[E0277]: the size for values of type `B` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:10:28
+  --> $DIR/unsized-bound.rs:10:47
    |
 LL | impl<A: ?Sized, B: ?Sized> Trait2<(A, B)> for (A, B) {}
-   |                 -          ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                 -                             ^^^^^^ doesn't have a size known at compile-time
    |                 |
    |                 this type parameter needs to be `std::marker::Sized`
    |
@@ -131,10 +131,10 @@ LL + impl<A, B: ?Sized> Trait2<(A, B)> for (A, B) {}
    |
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:14:9
+  --> $DIR/unsized-bound.rs:14:23
    |
 LL | impl<A> Trait3<A> for A where A: ?Sized {}
-   |      -  ^^^^^^^^^ doesn't have a size known at compile-time
+   |      -                ^ doesn't have a size known at compile-time
    |      |
    |      this type parameter needs to be `std::marker::Sized`
    |
@@ -154,10 +154,10 @@ LL | trait Trait3<A: ?Sized> {}
    |               ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:17:17
+  --> $DIR/unsized-bound.rs:17:31
    |
 LL | impl<A: ?Sized> Trait4<A> for A {}
-   |      -          ^^^^^^^^^ doesn't have a size known at compile-time
+   |      -                        ^ doesn't have a size known at compile-time
    |      |
    |      this type parameter needs to be `std::marker::Sized`
    |
@@ -177,10 +177,10 @@ LL | trait Trait4<A: ?Sized> {}
    |               ++++++++
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:20:12
+  --> $DIR/unsized-bound.rs:20:29
    |
 LL | impl<X, Y> Trait5<X, Y> for X where X: ?Sized {}
-   |      -     ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |      -                      ^ doesn't have a size known at compile-time
    |      |
    |      this type parameter needs to be `std::marker::Sized`
    |
@@ -200,10 +200,10 @@ LL | trait Trait5<A: ?Sized, B> {}
    |               ++++++++
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized-bound.rs:23:20
+  --> $DIR/unsized-bound.rs:23:37
    |
 LL | impl<X: ?Sized, Y> Trait6<X, Y> for X {}
-   |      -             ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |      -                              ^ doesn't have a size known at compile-time
    |      |
    |      this type parameter needs to be `std::marker::Sized`
    |
diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr
index 1390106a291..45bd533b5c6 100644
--- a/tests/ui/traits/ignore-err-impls.stderr
+++ b/tests/ui/traits/ignore-err-impls.stderr
@@ -2,9 +2,12 @@ error[E0412]: cannot find type `Type` in this scope
   --> $DIR/ignore-err-impls.rs:6:14
    |
 LL | impl Generic<Type> for S {}
-   |     -        ^^^^ not found in this scope
-   |     |
-   |     help: you might be missing a type parameter: `<Type>`
+   |              ^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<Type> Generic<Type> for S {}
+   |     ++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr
index b01bacdb87d..1f969efe114 100644
--- a/tests/ui/traits/impl-bounds-checking.stderr
+++ b/tests/ui/traits/impl-bounds-checking.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `isize: Clone2` is not satisfied
-  --> $DIR/impl-bounds-checking.rs:10:6
+  --> $DIR/impl-bounds-checking.rs:10:24
    |
 LL | impl Getter<isize> for isize {
-   |      ^^^^^^^^^^^^^ the trait `Clone2` is not implemented for `isize`
+   |                        ^^^^^ the trait `Clone2` is not implemented for `isize`
    |
 note: required by a bound in `Getter`
   --> $DIR/impl-bounds-checking.rs:6:17
diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
index 5572c6515ff..1bace8ab286 100644
--- a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
+++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
-  --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13
+  --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28
    |
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
-   |             ^^^^^^^^^^
+   |                            ^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
   --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'b` as defined he
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
    |         ^^
 note: ...so that the types are compatible
-  --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13
+  --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28
    |
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
-   |             ^^^^^^^^^^
+   |                            ^^^^^^^^^
    = note: expected `T1<'a>`
               found `T1<'_>`
 
diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr
index bb890cb99ee..4fe12731475 100644
--- a/tests/ui/traits/issue-43784-supertrait.stderr
+++ b/tests/ui/traits/issue-43784-supertrait.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-43784-supertrait.rs:8:9
+  --> $DIR/issue-43784-supertrait.rs:8:22
    |
 LL | impl<T> Complete for T {}
-   |         ^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |                      ^ the trait `Copy` is not implemented for `T`
    |
 note: required by a bound in `Complete`
   --> $DIR/issue-43784-supertrait.rs:4:21
diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr
index 0bb1f9ae035..aa8384e9805 100644
--- a/tests/ui/traits/issue-50480.stderr
+++ b/tests/ui/traits/issue-50480.stderr
@@ -2,9 +2,12 @@ error[E0412]: cannot find type `N` in this scope
   --> $DIR/issue-50480.rs:3:12
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<N>`
+   |            ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           +++
 
 error[E0412]: cannot find type `NotDefined` in this scope
   --> $DIR/issue-50480.rs:3:15
@@ -16,17 +19,23 @@ error[E0412]: cannot find type `N` in this scope
   --> $DIR/issue-50480.rs:3:12
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<N>`
+   |            ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct Foo<N>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           +++
 
 error[E0412]: cannot find type `NotDefined` in this scope
   --> $DIR/issue-50480.rs:3:15
    |
 LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |           -   ^^^^^^^^^^ not found in this scope
-   |           |
-   |           help: you might be missing a type parameter: `<NotDefined>`
+   |               ^^^^^^^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct Foo<NotDefined>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |           ++++++++++++
 
 error[E0412]: cannot find type `N` in this scope
   --> $DIR/issue-50480.rs:12:18
diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr
index 432ddf2dcdb..1675edc9ff0 100644
--- a/tests/ui/traits/issue-75627.stderr
+++ b/tests/ui/traits/issue-75627.stderr
@@ -2,9 +2,12 @@ error[E0412]: cannot find type `T` in this scope
   --> $DIR/issue-75627.rs:3:26
    |
 LL | unsafe impl Send for Foo<T> {}
-   |            -             ^ not found in this scope
-   |            |
-   |            help: you might be missing a type parameter: `<T>`
+   |                          ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | unsafe impl<T> Send for Foo<T> {}
+   |            +++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 7e781016e1f..8e7fd5f2557 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -30,9 +30,12 @@ error[E0412]: cannot find type `MISC` in this scope
   --> $DIR/issue-78372.rs:3:34
    |
 LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
-   |       -                          ^^^^ not found in this scope
-   |       |
-   |       help: you might be missing a type parameter: `, MISC`
+   |                                  ^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<T, MISC> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   |       ++++++
 
 error[E0658]: use of unstable library feature 'dispatch_from_dyn'
   --> $DIR/issue-78372.rs:1:5
diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr
index 6b314fa586d..85d903fadd1 100644
--- a/tests/ui/traits/issue-91594.stderr
+++ b/tests/ui/traits/issue-91594.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
-  --> $DIR/issue-91594.rs:10:6
+  --> $DIR/issue-91594.rs:10:19
    |
 LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
    |
    = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
 note: required for `Foo` to implement `Component<Foo>`
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index f137a298a7f..293cfbda86c 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -148,19 +148,24 @@ error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:115:12
    |
 LL |     let _: S::A;
-   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
+   |            ^^^^
+   |
+help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path
+   |
+LL |     let _: <S as Example>::A;
+   |            ~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:116:12
    |
 LL |     let _: S::B;
-   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::B`
+   |            ^^^^ help: use the fully-qualified path: `<S as assoc_ty::B>::B`
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:117:12
    |
 LL |     let _: S::C;
-   |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
+   |            ^^^^ help: use the fully-qualified path: `<S as assoc_ty::C>::C`
 
 error[E0624]: associated type `A` is private
   --> $DIR/item-privacy.rs:119:12
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr
index 85087282d3a..b4591778f8e 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr
@@ -1,11 +1,13 @@
 error[E0412]: cannot find type `Dst` in this scope
   --> $DIR/unknown_dst.rs:20:36
    |
-LL | fn should_gracefully_handle_unknown_dst() {
-   |                                        - help: you might be missing a type parameter: `<Dst>`
-...
 LL |     assert::is_transmutable::<Src, Dst, Context>();
    |                                    ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn should_gracefully_handle_unknown_dst<Dst>() {
+   |                                        +++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr
index 9bedbe87c3f..a55d71d8068 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr
+++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr
@@ -1,11 +1,13 @@
 error[E0412]: cannot find type `Src` in this scope
   --> $DIR/unknown_src.rs:20:31
    |
-LL | fn should_gracefully_handle_unknown_src() {
-   |                                        - help: you might be missing a type parameter: `<Src>`
-...
 LL |     assert::is_transmutable::<Src, Dst, Context>();
    |                               ^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn should_gracefully_handle_unknown_src<Src>() {
+   |                                        +++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/autoderef-with-param-env-error.stderr b/tests/ui/typeck/autoderef-with-param-env-error.stderr
index cde800336dd..182612d5ee7 100644
--- a/tests/ui/typeck/autoderef-with-param-env-error.stderr
+++ b/tests/ui/typeck/autoderef-with-param-env-error.stderr
@@ -1,11 +1,13 @@
 error[E0412]: cannot find type `T` in this scope
   --> $DIR/autoderef-with-param-env-error.rs:3:5
    |
-LL | fn foo()
-   |       - help: you might be missing a type parameter: `<T>`
-LL | where
 LL |     T: Send,
    |     ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn foo<T>()
+   |       +++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr
index 2b3b1b9efdf..5561673f3c6 100644
--- a/tests/ui/typeck/issue-104513-ice.stderr
+++ b/tests/ui/typeck/issue-104513-ice.stderr
@@ -1,10 +1,13 @@
 error[E0405]: cannot find trait `Oops` in this scope
   --> $DIR/issue-104513-ice.rs:3:19
    |
-LL | fn f() {
-   |     - help: you might be missing a type parameter: `<Oops>`
 LL |     let _: S<impl Oops> = S;
    |                   ^^^^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | fn f<Oops>() {
+   |     ++++++
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
   --> $DIR/issue-104513-ice.rs:3:14
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 5f7f6aa9f6e..72fccea8ae3 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -205,7 +205,12 @@ error[E0223]: ambiguous associated type
   --> $DIR/ufcs-partially-resolved.rs:36:12
    |
 LL |     let _: <u8 as Tr>::Y::NN;
-   |            ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<<u8 as Tr>::Y as Trait>::NN`
+   |            ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `NN` implemented for `<u8 as Tr>::Y`, you could use the fully-qualified path
+   |
+LL |     let _: <<u8 as Tr>::Y as Example>::NN;
+   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0599]: no associated item named `NN` found for type `u16` in the current scope
   --> $DIR/ufcs-partially-resolved.rs:38:20