about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/diagnostics.md46
-rw-r--r--.github/ISSUE_TEMPLATE/diagnostics.yaml65
-rw-r--r--.github/ISSUE_TEMPLATE/documentation.md31
-rw-r--r--.github/ISSUE_TEMPLATE/documentation.yaml38
-rw-r--r--.github/ISSUE_TEMPLATE/ice.md52
-rw-r--r--.github/ISSUE_TEMPLATE/ice.yaml82
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs74
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs63
-rw-r--r--compiler/rustc_infer/src/traits/util.rs18
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs28
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs10
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs30
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs54
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh2
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/deps.rs168
-rw-r--r--tests/mir-opt/building/custom/consts.rs4
-rw-r--r--tests/mir-opt/building/custom/consts.statics.built.after.mir4
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_no_prop.rs2
-rw-r--r--tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff4
-rw-r--r--tests/mir-opt/issues/issue_75439.rs1
-rw-r--r--tests/rustdoc-ui/invalid-syntax.stderr2
-rw-r--r--tests/ui/associated-types/issue-43784-associated-type.stderr5
-rw-r--r--tests/ui/closures/issue-84128.stderr7
-rw-r--r--tests/ui/closures/issue-87461.stderr21
-rw-r--r--tests/ui/derives/issue-91550.stderr34
-rw-r--r--tests/ui/generic-associated-types/issue-74824.stderr1
-rw-r--r--tests/ui/generic-associated-types/missing-bounds.stderr7
-rw-r--r--tests/ui/mismatched_types/issue-35030.stderr7
-rw-r--r--tests/ui/missing-trait-bounds/issue-35677.stderr2
-rw-r--r--tests/ui/parser/issues/issue-66473.stderrbin5260 -> 1061 bytes
-rw-r--r--tests/ui/parser/issues/issue-68629.stderrbin1831 -> 1637 bytes
-rw-r--r--tests/ui/parser/issues/issue-68730.stderrbin1226 -> 1266 bytes
-rw-r--r--tests/ui/parser/unicode-chars.rs4
-rw-r--r--tests/ui/parser/unicode-chars.stderr14
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr21
-rw-r--r--tests/ui/suggestions/sugg-else-for-closure.stderr7
-rw-r--r--tests/ui/traits/fn-trait-cast-diagnostic.rs26
-rw-r--r--tests/ui/traits/fn-trait-cast-diagnostic.stderr43
-rw-r--r--tests/ui/traits/issue-43784-supertrait.stderr5
-rw-r--r--tests/ui/traits/issue-52893.stderr7
-rw-r--r--tests/ui/traits/issue-99875.stderr5
-rw-r--r--tests/ui/traits/track-obligations.rs88
-rw-r--r--tests/ui/traits/track-obligations.stderr76
-rw-r--r--tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs28
-rw-r--r--tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr131
-rw-r--r--tests/ui/typeck/issue-46112.stderr7
-rw-r--r--tests/ui/typeck/issue-84768.stderr7
-rw-r--r--tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr14
-rw-r--r--triagebot.toml2
54 files changed, 1082 insertions, 307 deletions
diff --git a/.github/ISSUE_TEMPLATE/diagnostics.md b/.github/ISSUE_TEMPLATE/diagnostics.md
deleted file mode 100644
index a7b70cea927..00000000000
--- a/.github/ISSUE_TEMPLATE/diagnostics.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-name: Diagnostic issue
-about: Create a bug report or feature request for a change to `rustc`'s error output
-labels: A-diagnostics, T-compiler
----
-<!--
-Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
-along with any information you feel relevant to replicating the bug.
-
-If you cannot produce a minimal reproduction case (something that would work in
-isolation), please provide the steps or even link to a repository that causes
-the problematic output to occur.
--->
-
-Given the following code: <!-- Please provide a link to play.rust-lang.org -->
-
-```rust
-<code>
-```
-
-The current output is:
-
-```
-<rustc output>
-```
-
-<!-- The following is not always necessary. -->
-Ideally the output should look like:
-
-```
-<proposed output>
-```
-
-<!--
-If the problem is not self-explanatory, please provide a rationale for the
-change.
--->
-
-<!--
-If dramatically different output is caused by small changes, consider also
-adding them here.
-
-If you're using the stable version of the compiler, you should also check if the
-bug also exists in the beta or nightly versions. The output might also be
-different depending on the Edition.
--->
diff --git a/.github/ISSUE_TEMPLATE/diagnostics.yaml b/.github/ISSUE_TEMPLATE/diagnostics.yaml
new file mode 100644
index 00000000000..873fbaaf654
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/diagnostics.yaml
@@ -0,0 +1,65 @@
+name: Diagnostic issue
+description: Create a bug report or feature request for a change to `rustc`'s error output
+labels: ["A-diagnostics", "T-compiler"]
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thank you for filing a diagnostics bug report! 🐛
+
+        Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug.
+
+        If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur.
+  - type: textarea
+    id: code
+    attributes:
+      label: Code
+      description: Please provide code that can reproduce the problem
+      placeholder: code
+      render: Rust
+    validations:
+      required: true
+  - type: textarea
+    id: output
+    attributes:
+      label: Current output
+      description: Please provide the `rustc` output you see
+      placeholder: rustc output
+      render: Shell
+    validations:
+      required: true
+  - type: textarea
+    id: desired-output
+    attributes:
+      label: Desired output
+      description: Please provide what the output *should* be
+      placeholder: proposed output
+      render: Shell
+    validations:
+      required: false
+  - type: textarea
+    id: rationale
+    attributes:
+      label: Rationale and extra context
+      description: If the problem is not self-explanatory, please provide a rationale for the change.
+    validations:
+      required: false
+  - type: textarea
+    id: other-output
+    attributes:
+      label: Other cases
+      description: If dramatically different output is caused by small changes, consider also adding them here.
+      render: Rust
+    validations:
+      required: false
+  - type: markdown
+    attributes:
+      value: |
+        If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition.
+  - type: textarea
+    id: extra
+    attributes:
+      label: Anything else?
+      description: If you have more details you want to give us to reproduce this issue, please add it here
+    validations:
+      required: false
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md
deleted file mode 100644
index 9ccda17a6ef..00000000000
--- a/.github/ISSUE_TEMPLATE/documentation.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-name: Documentation problem
-about: Create a report for a documentation problem.
-labels: A-docs
----
-<!--
-
-Thank you for finding a documentation problem! 📚
-
-Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
-
-Note: If your issue is for one of these, please use their dedicated issue tracker instead:
-
-- The Rust Book: https://github.com/rust-lang/book/issues
-- Rust by Example: https://github.com/rust-lang/rust-by-example/issues
-- The Edition Guide: https://github.com/rust-lang/edition-guide/issues
-- The Cargo Book: https://github.com/rust-lang/cargo/issues
-- The Clippy Book: https://github.com/rust-lang/rust-clippy/issues
-- The Reference: https://github.com/rust-lang/reference/issues
-- The Rustonomicon: https://github.com/rust-lang/nomicon/issues
-- The Embedded Book: https://github.com/rust-embedded/book/issues
-
-All other documentation issues should be filed here.
-
-Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
-
--->
-
-### Location
-
-### Summary
diff --git a/.github/ISSUE_TEMPLATE/documentation.yaml b/.github/ISSUE_TEMPLATE/documentation.yaml
new file mode 100644
index 00000000000..712b32759ae
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/documentation.yaml
@@ -0,0 +1,38 @@
+name: Documentation problem
+description: Create a report for a documentation problem.
+labels: ["A-docs"]
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thank you for finding a documentation problem! 📚
+
+        Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
+
+        Note: If your issue is for one of these, please use their dedicated issue tracker instead:
+        - [The Rust Book](https://github.com/rust-lang/book/issues)
+        - [Rust by Example](https://github.com/rust-lang/rust-by-example/issues)
+        - [The Edition Guide](https://github.com/rust-lang/edition-guide/issues)
+        - [The Cargo Book](https://github.com/rust-lang/cargo/issues)
+        - [The Clippy Book](https://github.com/rust-lang/rust-clippy/issues)
+        - [The Reference](https://github.com/rust-lang/reference/issues)
+        - [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
+        - [The Embedded Book](https://github.com/rust-embedded/book/issues)
+
+        All other documentation issues should be filed here.
+
+        Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
+
+  - type: textarea
+    id: location
+    attributes:
+      label: Location
+    validations:
+      required: true 
+
+  - type: textarea
+    id: summary
+    attributes:
+      label: Summary
+    validations:
+      required: true 
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md
deleted file mode 100644
index 03bc4bab451..00000000000
--- a/.github/ISSUE_TEMPLATE/ice.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-name: Internal Compiler Error
-about: Create a report for an internal compiler error in rustc.
-labels: C-bug, I-ICE, T-compiler
----
-<!--
-Thank you for finding an Internal Compiler Error! 🧊  If possible, try to provide
-a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
-how to create smaller examples.
-
-http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
-
--->
-
-### Code
-
-```Rust
-<code>
-```
-
-
-### Meta
-<!--
-If you're using the stable version of the compiler, you should also check if the
-bug also exists in the beta or nightly versions.
--->
-
-`rustc --version --verbose`:
-```
-<version>
-```
-
-### Error output
-
-```
-<output>
-```
-
-<!--
-Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
-environment. E.g. `RUST_BACKTRACE=1 cargo build`.
--->
-<details><summary><strong>Backtrace</strong></summary>
-<p>
-
-```
-<backtrace>
-```
-
-</p>
-</details>
-
diff --git a/.github/ISSUE_TEMPLATE/ice.yaml b/.github/ISSUE_TEMPLATE/ice.yaml
new file mode 100644
index 00000000000..54136cc6d43
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/ice.yaml
@@ -0,0 +1,82 @@
+name: Internal Compiler Error
+description: Create a report for an internal compiler error in `rustc`
+labels: ["C-bug", "I-ICE", "T-compiler"]
+title: "[ICE]: "
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thank you for finding an Internal Compiler Error! 🧊
+
+        If possible, try to provide a minimal verifiable example.
+
+        You can read "[Rust Bug Minimization Patterns](http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/)" for how to create smaller examples.
+
+  - type: textarea
+    id: code
+    attributes:
+      label: Code
+      description: Please provide code or a link to a repository that can reproduce the problem
+      placeholder: code
+      render: Rust
+    validations:
+      required: false
+
+  - type: checkboxes
+    attributes:
+      label: Affected release channels
+      description: If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions
+      options:
+        - label: Previous Stable
+          required: false
+        - label: Current Stable
+          required: false
+        - label: Current Beta
+          required: false
+        - label: Current Nightly
+          required: false
+
+  - type: textarea
+    id: version
+    attributes:
+      label: Rust Version
+      description: Please provide the `rustc` version, `rustc --version --verbose`
+      placeholder: |
+        $ rustc --version --verbose
+        rustc 1.XX.Y (SHORTHASH DATE)
+        binary: rustc
+        commit-hash: LONGHASHVALUE
+        commit-date: DATE
+        host: PLATFORMTRIPLE
+        release: 1.XX.Y
+        LLVM version: XX.YY.ZZ
+      render: Shell
+    validations:
+      required: true
+
+  - type: textarea
+    id: output
+    attributes:
+      label: Current error output
+      description: Please provide the `rustc` output you see
+      placeholder: output
+      render: Shell
+    validations:
+      required: false
+
+  - type: textarea
+    id: backtrace
+    attributes:
+      label: Backtrace
+      description: Include a backtrace in the code block by setting `RUST_BACKTRACE=full` in your environment, e.g. `RUST_BACKTRACE=full cargo build`
+      render: Shell
+    validations:
+      required: true
+
+  - type: textarea
+    id: extra
+    attributes:
+      label: Anything else?
+      description: If you have more details you want to give us to reproduce this issue, please add it here
+    validations:
+      required: false
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index ee91b003771..5511d301775 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5601,6 +5601,7 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
+ "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.14.0",
  "ignore",
  "lazy_static",
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 6c128d0aa1a..665dc8b6a2f 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -85,6 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
         self.check_for_range_as_method_call(err, expr, expr_ty, expected);
         self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
+        self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty);
     }
 
     /// Requires that the two types unify, and prints an error message if
@@ -1941,4 +1942,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_label(block.span, "this block is missing a tail expression");
         }
     }
+
+    fn check_wrong_return_type_due_to_generic_arg(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        checked_ty: Ty<'tcx>,
+    ) {
+        let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; };
+        enum CallableKind {
+            Function,
+            Method,
+            Constructor,
+        }
+        let mut maybe_emit_help = |def_id: hir::def_id::DefId,
+                                   callable: rustc_span::symbol::Ident,
+                                   args: &[hir::Expr<'_>],
+                                   kind: CallableKind| {
+            let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
+            let fn_ty = self.tcx.bound_type_of(def_id).0;
+            if !fn_ty.is_fn() {
+                return;
+            }
+            let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
+            let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; };
+            if matches!(arg.kind(), ty::Param(_))
+                && fn_sig.output().contains(arg)
+                && self.node_ty(args[arg_idx].hir_id) == checked_ty
+            {
+                let mut multi_span: MultiSpan = parent_expr.span.into();
+                multi_span.push_span_label(
+                    args[arg_idx].span,
+                    format!(
+                        "this argument influences the {} of `{}`",
+                        if matches!(kind, CallableKind::Constructor) {
+                            "type"
+                        } else {
+                            "return type"
+                        },
+                        callable
+                    ),
+                );
+                err.span_help(
+                    multi_span,
+                    format!(
+                        "the {} `{}` due to the type of the argument passed",
+                        match kind {
+                            CallableKind::Function => "return type of this call is",
+                            CallableKind::Method => "return type of this call is",
+                            CallableKind::Constructor => "type constructed contains",
+                        },
+                        checked_ty
+                    ),
+                );
+            }
+        };
+        match parent_expr.kind {
+            hir::ExprKind::Call(fun, args) => {
+                let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; };
+                let hir::def::Res::Def(kind, def_id) = path.res else { return; };
+                let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) {
+                    CallableKind::Constructor
+                } else {
+                    CallableKind::Function
+                };
+                maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind);
+            }
+            hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
+                let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; };
+                maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
+            }
+            _ => return,
+        }
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index dd827777df9..15f6e117177 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1587,11 +1587,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         let o = self.resolve_vars_if_possible(o);
                         if !self.predicate_may_hold(&o) {
                             result = ProbeResult::NoMatch;
-                            possibly_unsatisfied_predicates.push((
-                                o.predicate,
-                                None,
-                                Some(o.cause),
-                            ));
+                            let parent_o = o.clone();
+                            let implied_obligations =
+                                traits::elaborate_obligations(self.tcx, vec![o]);
+                            for o in implied_obligations {
+                                let parent = if o == parent_o {
+                                    None
+                                } else {
+                                    if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
+                                        == self.tcx.lang_items().sized_trait()
+                                    {
+                                        // We don't care to talk about implicit `Sized` bounds.
+                                        continue;
+                                    }
+                                    Some(parent_o.predicate)
+                                };
+                                if !self.predicate_may_hold(&o) {
+                                    possibly_unsatisfied_predicates.push((
+                                        o.predicate,
+                                        parent,
+                                        Some(o.cause),
+                                    ));
+                                }
+                            }
                         }
                     }
                 }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 8166eb82990..f49fde04e84 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -505,19 +505,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                             _ => None,
                         };
-                        if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
-                            if let Some(g) = kind.generics() {
-                                let key = (
-                                    g.tail_span_for_predicate_suggestion(),
-                                    g.add_where_or_trailing_comma(),
-                                );
-                                type_params
-                                    .entry(key)
-                                    .or_insert_with(FxHashSet::default)
-                                    .insert(obligation.to_owned());
-                            }
+                        if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
+                            && let Some(g) = kind.generics()
+                        {
+                            let key = (
+                                g.tail_span_for_predicate_suggestion(),
+                                g.add_where_or_trailing_comma(),
+                            );
+                            type_params
+                                .entry(key)
+                                .or_insert_with(FxHashSet::default)
+                                .insert(obligation.to_owned());
+                            return true;
                         }
                     }
+                    false
                 };
             let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
                 let msg = format!(
@@ -692,7 +694,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "auto trait is invoked with no method error, but no error reported?",
                         );
                     }
-                    Some(_) => unreachable!(),
+                    Some(Node::Item(hir::Item {
+                        ident, kind: hir::ItemKind::Trait(..), ..
+                    })) => {
+                        skip_list.insert(p);
+                        let entry = spanned_predicates.entry(ident.span);
+                        let entry = entry.or_insert_with(|| {
+                            (FxHashSet::default(), FxHashSet::default(), Vec::new())
+                        });
+                        entry.0.insert(cause.span);
+                        entry.1.insert((ident.span, ""));
+                        entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
+                        entry.2.push(p);
+                    }
+                    Some(node) => unreachable!("encountered `{node:?}`"),
                     None => (),
                 }
             }
@@ -719,19 +734,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 unsatisfied_bounds = true;
             }
 
+            let mut suggested_bounds = FxHashSet::default();
             // The requirements that didn't have an `impl` span to show.
             let mut bound_list = unsatisfied_predicates
                 .iter()
                 .filter_map(|(pred, parent_pred, _cause)| {
+                    let mut suggested = false;
                     format_pred(*pred).map(|(p, self_ty)| {
-                        collect_type_param_suggestions(self_ty, *pred, &p);
+                        if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
+                            // We don't suggest `PartialEq` when we already suggest `Eq`.
+                        } else if !suggested_bounds.contains(pred) {
+                            if collect_type_param_suggestions(self_ty, *pred, &p) {
+                                suggested = true;
+                                suggested_bounds.insert(pred);
+                            }
+                        }
                         (
                             match parent_pred {
                                 None => format!("`{}`", &p),
                                 Some(parent_pred) => match format_pred(*parent_pred) {
                                     None => format!("`{}`", &p),
                                     Some((parent_p, _)) => {
-                                        collect_type_param_suggestions(self_ty, *parent_pred, &p);
+                                        if !suggested
+                                            && !suggested_bounds.contains(pred)
+                                            && !suggested_bounds.contains(parent_pred)
+                                        {
+                                            if collect_type_param_suggestions(
+                                                self_ty,
+                                                *parent_pred,
+                                                &p,
+                                            ) {
+                                                suggested_bounds.insert(pred);
+                                            }
+                                        }
                                         format!("`{}`\nwhich is required by `{}`", p, parent_p)
                                     }
                                 },
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8f0bd3a9abe..1817bbf9228 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,7 +1,7 @@
 use smallvec::smallvec;
 
 use crate::infer::outlives::components::{push_outlives_components, Component};
-use crate::traits::{Obligation, ObligationCause, PredicateObligation};
+use crate::traits::{self, Obligation, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_middle::ty::{self, ToPredicate, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -145,16 +145,28 @@ impl<'tcx> Elaborator<'tcx> {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
-                let obligations = predicates.predicates.iter().map(|&(mut pred, _)| {
+                let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
                     // when parent predicate is non-const, elaborate it to non-const predicates.
                     if data.constness == ty::BoundConstness::NotConst {
                         pred = pred.without_const(tcx);
                     }
 
+                    let cause = obligation.cause.clone().derived_cause(
+                        bound_predicate.rebind(data),
+                        |derived| {
+                            traits::ImplDerivedObligation(Box::new(
+                                traits::ImplDerivedObligationCause {
+                                    derived,
+                                    impl_def_id: data.def_id(),
+                                    span,
+                                },
+                            ))
+                        },
+                    );
                     predicate_obligation(
                         pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
                         obligation.param_env,
-                        obligation.cause.clone(),
+                        cause,
                     )
                 });
                 debug!(?data, ?obligations, "super_predicates");
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f027843e6b4..8761c23625b 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -79,7 +79,7 @@ impl<'a> StringReader<'a> {
     /// preceded by whitespace.
     fn next_token(&mut self) -> (Token, bool) {
         let mut preceded_by_whitespace = false;
-
+        let mut swallow_next_invalid = 0;
         // Skip trivial (whitespace & comments) tokens
         loop {
             let token = self.cursor.advance_token();
@@ -232,19 +232,34 @@ impl<'a> StringReader<'a> {
                 rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
 
                 rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
-                    let c = self.str_from(start).chars().next().unwrap();
+                    // Don't emit diagnostics for sequences of the same invalid token
+                    if swallow_next_invalid > 0 {
+                        swallow_next_invalid -= 1;
+                        continue;
+                    }
+                    let mut it = self.str_from_to_end(start).chars();
+                    let c = it.next().unwrap();
+                    let repeats = it.take_while(|c1| *c1 == c).count();
                     let mut err =
-                        self.struct_err_span_char(start, self.pos, "unknown start of token", c);
+                        self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c);
                     // FIXME: the lexer could be used to turn the ASCII version of unicode
                     // homoglyphs, instead of keeping a table in `check_for_substitution`into the
                     // token. Ideally, this should be inside `rustc_lexer`. However, we should
                     // first remove compound tokens like `<<` from `rustc_lexer`, and then add
                     // fancier error recovery to it, as there will be less overall work to do this
                     // way.
-                    let token = unicode_chars::check_for_substitution(self, start, c, &mut err);
+                    let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1);
                     if c == '\x00' {
                         err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
                     }
+                    if repeats > 0 {
+                        if repeats == 1 {
+                            err.note(format!("character appears once more"));
+                        } else {
+                            err.note(format!("character appears {repeats} more times"));
+                        }
+                        swallow_next_invalid = repeats;
+                    }
                     err.emit();
                     if let Some(token) = token {
                         token
@@ -486,6 +501,11 @@ impl<'a> StringReader<'a> {
         &self.src[self.src_index(start)..self.src_index(end)]
     }
 
+    /// Slice of the source text spanning from `start` until the end
+    fn str_from_to_end(&self, start: BytePos) -> &str {
+        &self.src[self.src_index(start)..]
+    }
+
     fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! {
         match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) {
             Err(RawStrError::InvalidStarter { bad_char }) => {
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index f1b50296e25..65479b341d7 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -337,10 +337,11 @@ pub(super) fn check_for_substitution<'a>(
     pos: BytePos,
     ch: char,
     err: &mut Diagnostic,
+    count: usize,
 ) -> Option<token::TokenKind> {
     let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
 
-    let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8()));
+    let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count));
 
     let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else {
         let msg = format!("substitution character not found for '{}'", ch);
@@ -369,7 +370,12 @@ pub(super) fn check_for_substitution<'a>(
             "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
             ch, u_name, ascii_char, ascii_name
         );
-        err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect);
+        err.span_suggestion(
+            span,
+            &msg,
+            ascii_char.to_string().repeat(count),
+            Applicability::MaybeIncorrect,
+        );
     }
     token.clone()
 }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index dd2b03988c3..645f8633941 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr {
 pub(super) enum LhsExpr {
     NotYetParsed,
     AttributesParsed(AttrWrapper),
-    AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
+    AlreadyParsed { expr: P<Expr>, starts_statement: bool },
 }
 
 impl From<Option<AttrWrapper>> for LhsExpr {
@@ -97,11 +97,11 @@ impl From<Option<AttrWrapper>> for LhsExpr {
 }
 
 impl From<P<Expr>> for LhsExpr {
-    /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed(expr)`.
+    /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed { expr, starts_statement: false }`.
     ///
     /// This conversion does not allocate.
     fn from(expr: P<Expr>) -> Self {
-        LhsExpr::AlreadyParsed(expr, false)
+        LhsExpr::AlreadyParsed { expr, starts_statement: false }
     }
 }
 
@@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
         lhs: LhsExpr,
     ) -> PResult<'a, P<Expr>> {
         let mut starts_stmt = false;
-        let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+        let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs {
             starts_stmt = starts_statement;
             expr
         } else {
@@ -562,17 +562,23 @@ impl<'a> Parser<'a> {
 
         // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
         match this.token.uninterpolate().kind {
-            token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr`
-            token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr`
+            // `!expr`
+            token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
+            // `~expr`
+            token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
+            // `-expr`
             token::BinOp(token::Minus) => {
                 make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
-            } // `-expr`
+            }
+            // `*expr`
             token::BinOp(token::Star) => {
                 make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
-            } // `*expr`
+            }
+            // `&expr` and `&&expr`
             token::BinOp(token::And) | token::AndAnd => {
                 make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
             }
+            // `+lit`
             token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
                 let mut err =
                     LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
@@ -587,7 +593,7 @@ impl<'a> Parser<'a> {
 
                 this.bump();
                 this.parse_prefix_expr(None)
-            } // `+expr`
+            }
             // Recover from `++x`:
             token::BinOp(token::Plus)
                 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
@@ -624,7 +630,7 @@ impl<'a> Parser<'a> {
         Ok((span, self.mk_unary(op, expr)))
     }
 
-    // Recover on `!` suggesting for bitwise negation instead.
+    /// Recover on `~expr` in favor of `!expr`.
     fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
         self.sess.emit_err(TildeAsUnaryOperator(lo));
 
@@ -651,7 +657,6 @@ impl<'a> Parser<'a> {
 
     /// Recover on `not expr` in favor of `!expr`.
     fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
-        // Emit the error...
         let negated_token = self.look_ahead(1, |t| t.clone());
 
         let sub_diag = if negated_token.is_numeric_lit() {
@@ -672,7 +677,6 @@ impl<'a> Parser<'a> {
             ),
         });
 
-        // ...and recover!
         self.parse_unary_expr(lo, UnOp::Not)
     }
 
@@ -1593,7 +1597,7 @@ impl<'a> Parser<'a> {
                     vis.0
                 };
 
-                // Suggestion involves adding a (as of time of writing this, unstable) labeled block.
+                // Suggestion involves adding a labeled block.
                 //
                 // If there are no breaks that may use this label, suggest removing the label and
                 // recover to the unmodified expression.
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 1e5c2834960..4ff9927aab5 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -164,7 +164,10 @@ impl<'a> Parser<'a> {
             // Perform this outside of the `collect_tokens_trailing_token` closure,
             // since our outer attributes do not apply to this part of the expression
             let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
+                this.parse_assoc_expr_with(
+                    0,
+                    LhsExpr::AlreadyParsed { expr, starts_statement: true },
+                )
             })?;
             Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
         } else {
@@ -198,7 +201,10 @@ impl<'a> Parser<'a> {
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
             let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
+            let e = self.parse_assoc_expr_with(
+                0,
+                LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
+            )?;
             StmtKind::Expr(e)
         };
         Ok(self.mk_stmt(lo.to(hi), kind))
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 0c7ffb056cc..41a64a844ce 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -374,6 +374,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         })
     }
 }
+
 impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn report_fulfillment_errors(
         &self,
@@ -852,6 +853,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         let mut suggested =
                             self.suggest_dereferences(&obligation, &mut err, trait_predicate);
                         suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
+                        let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
+                        suggested = if let &[cand] = &impl_candidates[..] {
+                            let cand = cand.trait_ref;
+                            if let (ty::FnPtr(_), ty::FnDef(..)) =
+                                (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
+                            {
+                                err.span_suggestion(
+                                    span.shrink_to_hi(),
+                                    format!(
+                                        "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
+                                        cand.print_only_trait_path(),
+                                        cand.self_ty(),
+                                    ),
+                                    format!(" as {}", cand.self_ty()),
+                                    Applicability::MaybeIncorrect,
+                                );
+                                true
+                            } else {
+                                false
+                            }
+                        } else {
+                            false
+                        } || suggested;
                         suggested |=
                             self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
                         suggested |= self.suggest_semicolon_removal(
@@ -1968,27 +1992,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             candidates.sort();
             candidates.dedup();
             let len = candidates.len();
-            if candidates.len() == 0 {
+            if candidates.is_empty() {
                 return false;
             }
-            if candidates.len() == 1 {
-                let ty_desc = match candidates[0].self_ty().kind() {
-                    ty::FnPtr(_) => Some("fn pointer"),
-                    _ => None,
-                };
-                let the_desc = match ty_desc {
-                    Some(desc) => format!(" implemented for {} `", desc),
-                    None => " implemented for `".to_string(),
-                };
+            if let &[cand] = &candidates[..] {
+                let (desc, mention_castable) =
+                    match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
+                        (ty::FnPtr(_), ty::FnDef(..)) => {
+                            (" implemented for fn pointer `", ", cast using `as`")
+                        }
+                        (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
+                        _ => (" implemented for `", ""),
+                    };
                 err.highlighted_help(vec![
-                    (
-                        format!("the trait `{}` ", candidates[0].print_only_trait_path()),
-                        Style::NoStyle,
-                    ),
+                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
                     ("is".to_string(), Style::Highlight),
-                    (the_desc, Style::NoStyle),
-                    (candidates[0].self_ty().to_string(), Style::Highlight),
+                    (desc.to_string(), Style::NoStyle),
+                    (cand.self_ty().to_string(), Style::Highlight),
                     ("`".to_string(), Style::NoStyle),
+                    (mention_castable.to_string(), Style::NoStyle),
                 ]);
                 return true;
             }
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index 67cee0148b2..5fbce36c39d 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin"
 git clone https://github.com/WebAssembly/wasi-libc
 
 cd wasi-libc
-git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0
+git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8
 make -j$(nproc) \
     CC="$bin/clang" \
     NM="$bin/llvm-nm" \
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index fff83a1d097..19812fc6f55 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -6,6 +6,7 @@ autobins = false
 
 [dependencies]
 cargo_metadata = "0.14"
+cargo-platform = "0.1.2"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
 lazy_static = "1"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 845eb5af0d6..bc2edf634de 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,7 +1,7 @@
 //! Checks the licenses of third-party dependencies.
 
-use cargo_metadata::{Metadata, Package, PackageId, Resolve};
-use std::collections::{BTreeSet, HashSet};
+use cargo_metadata::{DepKindInfo, Metadata, Package, PackageId};
+use std::collections::HashSet;
 use std::path::Path;
 
 /// These are licenses that are allowed for all crates, including the runtime,
@@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "autocfg",
     "bitflags",
     "block-buffer",
-    "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "cc",
     "cfg-if",
     "chalk-derive",
     "chalk-engine",
     "chalk-ir",
     "chalk-solve",
-    "chrono",
     "convert_case", // dependency of derive_more
     "compiler_builtins",
     "cpufeatures",
@@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "dlmalloc",
     "either",
     "ena",
-    "env_logger",
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
-    "filetime",
     "fixedbitset",
     "flate2",
     "fluent-bundle",
@@ -142,13 +138,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "gsgdt",
     "hashbrown",
     "hermit-abi",
-    "humantime",
     "icu_list",
     "icu_locid",
     "icu_provider",
     "icu_provider_adapters",
     "icu_provider_macros",
-    "if_chain",
     "indexmap",
     "instant",
     "intl-memoizer",
@@ -156,7 +150,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "itertools",
     "itoa",
     "jobserver",
-    "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "lazy_static",
     "libc",
     "libloading",
@@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "memmap2",
     "memoffset",
     "miniz_oxide",
-    "num-integer",
-    "num-traits",
     "num_cpus",
     "object",
     "odht",
@@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "proc-macro2",
     "psm",
     "punycode",
-    "quick-error",
     "quote",
     "rand",
     "rand_chacha",
@@ -235,7 +225,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "thiserror-impl",
     "thorin-dwp",
     "thread_local",
-    "time",
     "tinystr",
     "tinyvec",
     "tinyvec_macros",
@@ -268,13 +257,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "valuable",
     "version_check",
     "wasi",
-    // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
-    "wasm-bindgen",
-    "wasm-bindgen-backend",
-    "wasm-bindgen-macro",
-    "wasm-bindgen-macro-support",
-    "wasm-bindgen-shared",
-    // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
     "winapi",
     "winapi-i686-pc-windows-gnu",
     "winapi-util",
@@ -485,73 +467,55 @@ fn check_permitted_dependencies(
     restricted_dependency_crates: &[&'static str],
     bad: &mut bool,
 ) {
+    let mut deps = HashSet::new();
+    for to_check in restricted_dependency_crates {
+        let to_check = pkg_from_name(metadata, to_check);
+        use cargo_platform::Cfg;
+        use std::str::FromStr;
+        // We don't expect the compiler to ever run on wasm32, so strip
+        // out those dependencies to avoid polluting the permitted list.
+        deps_of_filtered(metadata, &to_check.id, &mut deps, &|dep_kinds| {
+            dep_kinds.iter().any(|dep_kind| {
+                dep_kind
+                    .target
+                    .as_ref()
+                    .map(|target| {
+                        !target.matches(
+                            "wasm32-unknown-unknown",
+                            &[
+                                Cfg::from_str("target_arch=\"wasm32\"").unwrap(),
+                                Cfg::from_str("target_os=\"unknown\"").unwrap(),
+                            ],
+                        )
+                    })
+                    .unwrap_or(true)
+            })
+        });
+    }
+
     // Check that the PERMITTED_DEPENDENCIES does not have unused entries.
-    for name in permitted_dependencies {
-        if !metadata.packages.iter().any(|p| p.name == *name) {
+    for permitted in permitted_dependencies {
+        if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
             tidy_error!(
                 bad,
-                "could not find allowed package `{}`\n\
+                "could not find allowed package `{permitted}`\n\
                 Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
-                name
             );
         }
     }
-    // Get the list in a convenient form.
-    let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
-
-    // Check dependencies.
-    let mut visited = BTreeSet::new();
-    let mut unapproved = BTreeSet::new();
-    for &krate in restricted_dependency_crates.iter() {
-        let pkg = pkg_from_name(metadata, krate);
-        let mut bad =
-            check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg);
-        unapproved.append(&mut bad);
-    }
-
-    if !unapproved.is_empty() {
-        tidy_error!(bad, "Dependencies for {} not explicitly permitted:", descr);
-        for dep in unapproved {
-            println!("* {dep}");
-        }
-    }
-}
-
-/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
-/// the list of permitted dependencies. Returns a list of disallowed dependencies.
-fn check_crate_dependencies<'a>(
-    permitted_dependencies: &'a HashSet<&'static str>,
-    metadata: &'a Metadata,
-    visited: &mut BTreeSet<&'a PackageId>,
-    krate: &'a Package,
-) -> BTreeSet<&'a PackageId> {
-    // This will contain bad deps.
-    let mut unapproved = BTreeSet::new();
-
-    // Check if we have already visited this crate.
-    if visited.contains(&krate.id) {
-        return unapproved;
-    }
 
-    visited.insert(&krate.id);
+    // Get in a convenient form.
+    let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
 
-    // If this path is in-tree, we don't require it to be explicitly permitted.
-    if krate.source.is_some() {
-        // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
-        if !permitted_dependencies.contains(krate.name.as_str()) {
-            unapproved.insert(&krate.id);
+    for dep in deps {
+        let dep = pkg_from_id(metadata, dep);
+        // If this path is in-tree, we don't require it to be explicitly permitted.
+        if dep.source.is_some() {
+            if !permitted_dependencies.contains(dep.name.as_str()) {
+                tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
+            }
         }
     }
-
-    // Do a DFS in the crate graph.
-    let to_check = deps_of(metadata, &krate.id);
-
-    for dep in to_check {
-        let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep);
-        unapproved.append(&mut bad);
-    }
-
-    unapproved
 }
 
 /// Prevents multiple versions of some expensive crates.
@@ -588,24 +552,6 @@ fn check_crate_duplicate(
     }
 }
 
-/// Returns a list of dependencies for the given package.
-fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
-    let resolve = metadata.resolve.as_ref().unwrap();
-    let node = resolve
-        .nodes
-        .iter()
-        .find(|n| &n.id == pkg_id)
-        .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
-    node.deps
-        .iter()
-        .map(|dep| {
-            metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| {
-                panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id)
-            })
-        })
-        .collect()
-}
-
 /// Finds a package with the given name.
 fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
     let mut i = metadata.packages.iter().filter(|p| p.name == name);
@@ -615,41 +561,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package
     result
 }
 
+fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package {
+    metadata.packages.iter().find(|p| &p.id == id).unwrap()
+}
+
 /// Finds all the packages that are in the rust runtime.
 fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
-    let resolve = metadata.resolve.as_ref().unwrap();
     let mut result = HashSet::new();
     for name in RUNTIME_CRATES {
         let id = &pkg_from_name(metadata, name).id;
-        normal_deps_of_r(resolve, id, &mut result);
+        deps_of_filtered(metadata, id, &mut result, &|_| true);
     }
     result
 }
 
-/// Recursively find all normal dependencies.
-fn normal_deps_of_r<'a>(
-    resolve: &'a Resolve,
+/// Recursively find all dependencies.
+fn deps_of_filtered<'a>(
+    metadata: &'a Metadata,
     pkg_id: &'a PackageId,
     result: &mut HashSet<&'a PackageId>,
+    filter: &dyn Fn(&[DepKindInfo]) -> bool,
 ) {
     if !result.insert(pkg_id) {
         return;
     }
-    let node = resolve
+    let node = metadata
+        .resolve
+        .as_ref()
+        .unwrap()
         .nodes
         .iter()
         .find(|n| &n.id == pkg_id)
         .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
     for dep in &node.deps {
-        normal_deps_of_r(resolve, &dep.pkg, result);
+        if !filter(&dep.dep_kinds) {
+            continue;
+        }
+        deps_of_filtered(metadata, &dep.pkg, result, filter);
     }
 }
 
+fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
+    let resolve = metadata.resolve.as_ref().unwrap();
+    let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap();
+    node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect()
+}
+
 fn check_rustfix(metadata: &Metadata, bad: &mut bool) {
     let cargo = pkg_from_name(metadata, "cargo");
     let compiletest = pkg_from_name(metadata, "compiletest");
-    let cargo_deps = deps_of(metadata, &cargo.id);
-    let compiletest_deps = deps_of(metadata, &compiletest.id);
+    let cargo_deps = direct_deps_of(metadata, &cargo.id);
+    let compiletest_deps = direct_deps_of(metadata, &compiletest.id);
     let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap();
     let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap();
     if cargo_rustfix.version != compiletest_rustfix.version {
diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs
index ff4fe1a9324..16d10eb5968 100644
--- a/tests/mir-opt/building/custom/consts.rs
+++ b/tests/mir-opt/building/custom/consts.rs
@@ -18,8 +18,8 @@ fn consts<const C: u32>() {
     })
 }
 
-static S: i32 = 5;
-static mut T: i32 = 10;
+static S: i32 = 0x05050505;
+static mut T: i32 = 0x0a0a0a0a;
 // EMIT_MIR consts.statics.built.after.mir
 #[custom_mir(dialect = "built")]
 fn statics() {
diff --git a/tests/mir-opt/building/custom/consts.statics.built.after.mir b/tests/mir-opt/building/custom/consts.statics.built.after.mir
index ee768e263ec..bfef976aa02 100644
--- a/tests/mir-opt/building/custom/consts.statics.built.after.mir
+++ b/tests/mir-opt/building/custom/consts.statics.built.after.mir
@@ -19,9 +19,9 @@ fn statics() -> () {
 }
 
 alloc2 (static: T, size: 4, align: 4) {
-    0a 00 00 00                                     │ ....
+    0a 0a 0a 0a                                     │ ....
 }
 
 alloc1 (static: S, size: 4, align: 4) {
-    05 00 00 00                                     │ ....
+    05 05 05 05                                     │ ....
 }
diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
index b9d551c5e5f..7fa29cccd50 100644
--- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
@@ -38,6 +38,6 @@
   }
   
   alloc1 (static: STATIC, size: 4, align: 4) {
-      2a 00 00 00                                     │ *...
+      42 42 42 42                                     │ BBBB
   }
   
diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
index 8c23c5fcf0f..b69ec931a63 100644
--- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
@@ -1,7 +1,7 @@
 // unit-test
 // compile-flags: -O
 
-static mut STATIC: u32 = 42;
+static mut STATIC: u32 = 0x42424242;
 
 // EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff
 fn main() {
diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index 1c69a6232d6..93804780371 100644
--- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -26,7 +26,7 @@
           _3 = _1;                         // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52
           _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53
                                            // mir::Constant
-                                           // + span: $DIR/issue_75439.rs:7:37: 7:46
+                                           // + span: $DIR/issue_75439.rs:8:37: 8:46
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) }
       }
   
@@ -49,7 +49,7 @@
           _6 = _4;                         // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35
           _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36
                                            // mir::Constant
-                                           // + span: $DIR/issue_75439.rs:10:23: 10:32
+                                           // + span: $DIR/issue_75439.rs:11:23: 11:32
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs
index ae2e036312e..4c749a150c0 100644
--- a/tests/mir-opt/issues/issue_75439.rs
+++ b/tests/mir-opt/issues/issue_75439.rs
@@ -1,4 +1,5 @@
 // EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff
+// ignore-endian-big
 
 use std::mem::transmute;
 
diff --git a/tests/rustdoc-ui/invalid-syntax.stderr b/tests/rustdoc-ui/invalid-syntax.stderr
index 597d19e748c..6140a06c555 100644
--- a/tests/rustdoc-ui/invalid-syntax.stderr
+++ b/tests/rustdoc-ui/invalid-syntax.stderr
@@ -77,8 +77,6 @@ LL | ///     ```
    |         ^^^
    |
    = note: error from rustc: unknown start of token: `
-   = note: error from rustc: unknown start of token: `
-   = note: error from rustc: unknown start of token: `
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:64:5
diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr
index f1677b822b4..50fa7d1ac4d 100644
--- a/tests/ui/associated-types/issue-43784-associated-type.stderr
+++ b/tests/ui/associated-types/issue-43784-associated-type.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL |     type Assoc = T;
    |                  ^ the trait `Copy` is not implemented for `T`
    |
+note: required for `<T as Complete>::Assoc` to implement `Partial<T>`
+  --> $DIR/issue-43784-associated-type.rs:1:11
+   |
+LL | pub trait Partial<X: ?Sized>: Copy {
+   |           ^^^^^^^
 note: required by a bound in `Complete::Assoc`
   --> $DIR/issue-43784-associated-type.rs:5:17
    |
diff --git a/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr
index 59607afec8f..1cd8949b8c4 100644
--- a/tests/ui/closures/issue-84128.stderr
+++ b/tests/ui/closures/issue-84128.stderr
@@ -6,6 +6,13 @@ LL |         Foo(())
    |         |
    |         arguments to this struct are incorrect
    |
+help: the type constructed contains `()` due to the type of the argument passed
+  --> $DIR/issue-84128.rs:13:9
+   |
+LL |         Foo(())
+   |         ^^^^--^
+   |             |
+   |             this argument influences the type of `Foo`
 note: tuple struct defined here
   --> $DIR/issue-84128.rs:5:8
    |
diff --git a/tests/ui/closures/issue-87461.stderr b/tests/ui/closures/issue-87461.stderr
index 72337892734..b492251c016 100644
--- a/tests/ui/closures/issue-87461.stderr
+++ b/tests/ui/closures/issue-87461.stderr
@@ -6,6 +6,13 @@ LL |     Ok(())
    |     |
    |     arguments to this enum variant are incorrect
    |
+help: the type constructed contains `()` due to the type of the argument passed
+  --> $DIR/issue-87461.rs:10:5
+   |
+LL |     Ok(())
+   |     ^^^--^
+   |        |
+   |        this argument influences the type of `Ok`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 
@@ -17,6 +24,13 @@ LL |     Ok(())
    |     |
    |     arguments to this enum variant are incorrect
    |
+help: the type constructed contains `()` due to the type of the argument passed
+  --> $DIR/issue-87461.rs:17:5
+   |
+LL |     Ok(())
+   |     ^^^--^
+   |        |
+   |        this argument influences the type of `Ok`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 
@@ -28,6 +42,13 @@ LL |         Ok(())
    |         |
    |         arguments to this enum variant are incorrect
    |
+help: the type constructed contains `()` due to the type of the argument passed
+  --> $DIR/issue-87461.rs:26:9
+   |
+LL |         Ok(())
+   |         ^^^--^
+   |            |
+   |            this argument influences the type of `Ok`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 
diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr
index bf0bb3fbdf8..af03f0e5e5f 100644
--- a/tests/ui/derives/issue-91550.stderr
+++ b/tests/ui/derives/issue-91550.stderr
@@ -6,12 +6,15 @@ LL | struct Value(u32);
    | |
    | doesn't satisfy `Value: Eq`
    | doesn't satisfy `Value: Hash`
+   | doesn't satisfy `Value: PartialEq`
 ...
 LL |     hs.insert(Value(0));
    |        ^^^^^^
    |
    = note: the following trait bounds were not satisfied:
            `Value: Eq`
+           `Value: PartialEq`
+           which is required by `Value: Eq`
            `Value: Hash`
 help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
    |
@@ -22,7 +25,10 @@ error[E0599]: the method `use_eq` exists for struct `Object<NoDerives>`, but its
   --> $DIR/issue-91550.rs:26:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Eq`
+   | --------------------
+   | |
+   | doesn't satisfy `NoDerives: Eq`
+   | doesn't satisfy `NoDerives: PartialEq`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_eq` not found for this struct
@@ -37,6 +43,9 @@ LL | impl<T: Eq> Object<T> {
    |         ^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: PartialEq`
+           which is required by `NoDerives: Eq`
 help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
    |
 LL | #[derive(Eq, PartialEq)]
@@ -46,7 +55,12 @@ error[E0599]: the method `use_ord` exists for struct `Object<NoDerives>`, but it
   --> $DIR/issue-91550.rs:27:9
    |
 LL | pub struct NoDerives;
-   | -------------------- doesn't satisfy `NoDerives: Ord`
+   | --------------------
+   | |
+   | doesn't satisfy `NoDerives: Eq`
+   | doesn't satisfy `NoDerives: Ord`
+   | doesn't satisfy `NoDerives: PartialEq`
+   | doesn't satisfy `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
    | ---------------- method `use_ord` not found for this struct
@@ -61,6 +75,13 @@ LL | impl<T: Ord> Object<T> {
    |         ^^^  ---------
    |         |
    |         unsatisfied trait bound introduced here
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: PartialOrd`
+           which is required by `NoDerives: Ord`
+           `NoDerives: PartialEq`
+           which is required by `NoDerives: Ord`
+           `NoDerives: Eq`
+           which is required by `NoDerives: Ord`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
@@ -72,7 +93,9 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object<NoD
 LL | pub struct NoDerives;
    | --------------------
    | |
+   | doesn't satisfy `NoDerives: Eq`
    | doesn't satisfy `NoDerives: Ord`
+   | doesn't satisfy `NoDerives: PartialEq`
    | doesn't satisfy `NoDerives: PartialOrd`
 LL |
 LL | struct Object<T>(T);
@@ -91,6 +114,13 @@ LL | impl<T: Ord + PartialOrd> Object<T> {
    |         |     |
    |         |     unsatisfied trait bound introduced here
    |         unsatisfied trait bound introduced here
+   = note: the following trait bounds were not satisfied:
+           `NoDerives: PartialEq`
+           which is required by `NoDerives: Ord`
+           `NoDerives: Eq`
+           which is required by `NoDerives: Ord`
+           `NoDerives: PartialEq`
+           which is required by `NoDerives: PartialOrd`
 help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
    |
 LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr
index 623adb1c2ad..e5638d90ee8 100644
--- a/tests/ui/generic-associated-types/issue-74824.stderr
+++ b/tests/ui/generic-associated-types/issue-74824.stderr
@@ -17,6 +17,7 @@ LL |     type Copy<T>: Copy = Box<T>;
    |                          ^^^^^^ the trait `Clone` is not implemented for `T`
    |
    = note: required for `Box<T>` to implement `Clone`
+   = note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy`
 note: required by a bound in `UnsafeCopy::Copy`
   --> $DIR/issue-74824.rs:6:19
    |
diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr
index c913483a874..9f669b9a521 100644
--- a/tests/ui/generic-associated-types/missing-bounds.stderr
+++ b/tests/ui/generic-associated-types/missing-bounds.stderr
@@ -23,6 +23,13 @@ LL |         A(self.0 + rhs.0)
    |
    = note: expected type parameter `B`
              found associated type `<B as Add>::Output`
+help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
+  --> $DIR/missing-bounds.rs:11:9
+   |
+LL |         A(self.0 + rhs.0)
+   |         ^^--------------^
+   |           |
+   |           this argument influences the type of `A`
 note: tuple struct defined here
   --> $DIR/missing-bounds.rs:5:8
    |
diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr
index 680aff1726f..de4e067fead 100644
--- a/tests/ui/mismatched_types/issue-35030.stderr
+++ b/tests/ui/mismatched_types/issue-35030.stderr
@@ -11,6 +11,13 @@ LL |         Some(true)
    |
    = note: expected type parameter `bool` (type parameter `bool`)
                         found type `bool` (`bool`)
+help: the type constructed contains `bool` due to the type of the argument passed
+  --> $DIR/issue-35030.rs:9:9
+   |
+LL |         Some(true)
+   |         ^^^^^----^
+   |              |
+   |              this argument influences the type of `Some`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr
index a2201b946a6..05d3de80d84 100644
--- a/tests/ui/missing-trait-bounds/issue-35677.stderr
+++ b/tests/ui/missing-trait-bounds/issue-35677.stderr
@@ -6,6 +6,8 @@ LL |     this.is_subset(other)
    |
    = note: the following trait bounds were not satisfied:
            `T: Eq`
+           `T: PartialEq`
+           which is required by `T: Eq`
            `T: Hash`
 help: consider restricting the type parameters to satisfy the trait bounds
    |
diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr
index 8a16d7f9551..0e8b0a5da22 100644
--- a/tests/ui/parser/issues/issue-66473.stderr
+++ b/tests/ui/parser/issues/issue-66473.stderr
Binary files differdiff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr
index b2c7dddc801..43a903e6c46 100644
--- a/tests/ui/parser/issues/issue-68629.stderr
+++ b/tests/ui/parser/issues/issue-68629.stderr
Binary files differdiff --git a/tests/ui/parser/issues/issue-68730.stderr b/tests/ui/parser/issues/issue-68730.stderr
index 6585a19d954..5bca5bbebea 100644
--- a/tests/ui/parser/issues/issue-68730.stderr
+++ b/tests/ui/parser/issues/issue-68730.stderr
Binary files differdiff --git a/tests/ui/parser/unicode-chars.rs b/tests/ui/parser/unicode-chars.rs
index 89ae85ec990..ba35e95c82a 100644
--- a/tests/ui/parser/unicode-chars.rs
+++ b/tests/ui/parser/unicode-chars.rs
@@ -2,4 +2,8 @@ fn main() {
     let y = 0;
     //~^ ERROR unknown start of token: \u{37e}
     //~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
+        let x = 0;
+    //~^ ERROR unknown start of token: \u{a0}
+    //~^^ NOTE character appears 3 more times
+    //~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
 }
diff --git a/tests/ui/parser/unicode-chars.stderr b/tests/ui/parser/unicode-chars.stderr
index 0cfe9240e85..6a5b27872e7 100644
--- a/tests/ui/parser/unicode-chars.stderr
+++ b/tests/ui/parser/unicode-chars.stderr
@@ -9,5 +9,17 @@ help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), b
 LL |     let y = 0;
    |              ~
 
-error: aborting due to previous error
+error: unknown start of token: \u{a0}
+  --> $DIR/unicode-chars.rs:5:5
+   |
+LL |         let x = 0;
+   |     ^^^^
+   |
+   = note: character appears 3 more times
+help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
+   |
+LL |         let x = 0;
+   |     ++++
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
index 44a39efdf25..bc097bf6eb4 100644
--- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -11,6 +11,13 @@ LL |     let _: Option<(i32, bool)> = Some(1, 2);
    |                                       ^
    = note: expected tuple `(i32, bool)`
                found type `{integer}`
+help: the type constructed contains `{integer}` due to the type of the argument passed
+  --> $DIR/args-instead-of-tuple-errors.rs:6:34
+   |
+LL |     let _: Option<(i32, bool)> = Some(1, 2);
+   |                                  ^^^^^-^^^^
+   |                                       |
+   |                                       this argument influences the type of `Some`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: remove the extra argument
@@ -64,6 +71,13 @@ LL |     let _: Option<(i32,)> = Some(5_usize);
    |
    = note: expected tuple `(i32,)`
                found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+  --> $DIR/args-instead-of-tuple-errors.rs:14:29
+   |
+LL |     let _: Option<(i32,)> = Some(5_usize);
+   |                             ^^^^^-------^
+   |                                  |
+   |                                  this argument influences the type of `Some`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
@@ -77,6 +91,13 @@ LL |     let _: Option<(i32,)> = Some((5_usize));
    |
    = note: expected tuple `(i32,)`
                found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+  --> $DIR/args-instead-of-tuple-errors.rs:17:29
+   |
+LL |     let _: Option<(i32,)> = Some((5_usize));
+   |                             ^^^^^---------^
+   |                                  |
+   |                                  this argument influences the type of `Some`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr
index 5f59d0f541c..7f05832bcd7 100644
--- a/tests/ui/suggestions/sugg-else-for-closure.stderr
+++ b/tests/ui/suggestions/sugg-else-for-closure.stderr
@@ -8,6 +8,13 @@ LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
    |
    = note: expected reference `&str`
                 found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
+help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed
+  --> $DIR/sugg-else-for-closure.rs:6:14
+   |
+LL |     let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+   |              ^^^^^^^^^^^^-------------------------------^
+   |                          |
+   |                          this argument influences the return type of `unwrap_or`
 note: associated function defined here
   --> $SRC_DIR/core/src/option.rs:LL:COL
 help: try calling `unwrap_or_else` instead
diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs
new file mode 100644
index 00000000000..e20aa210e58
--- /dev/null
+++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs
@@ -0,0 +1,26 @@
+// There are two different instances to check that even if
+// the trait is implemented for the output of a function,
+// it will still be displayed if the function itself implements a trait.
+trait Foo {}
+
+impl Foo for fn() -> bool {}
+impl Foo for bool {}
+
+fn example() -> bool {
+    true
+}
+
+trait NoOtherFoo {}
+
+impl NoOtherFoo for fn() -> bool {}
+
+fn do_on_foo(v: impl Foo) {}
+fn do_on_single_foo(v: impl NoOtherFoo) {}
+
+fn main() {
+    do_on_foo(example);
+    //~^ ERROR the trait bound
+
+    do_on_single_foo(example);
+    //~^ ERROR the trait bound
+}
diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr
new file mode 100644
index 00000000000..6851dcdd504
--- /dev/null
+++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr
@@ -0,0 +1,43 @@
+error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied
+  --> $DIR/fn-trait-cast-diagnostic.rs:21:15
+   |
+LL |     do_on_foo(example);
+   |     --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `do_on_foo`
+  --> $DIR/fn-trait-cast-diagnostic.rs:17:22
+   |
+LL | fn do_on_foo(v: impl Foo) {}
+   |                      ^^^ required by this bound in `do_on_foo`
+help: use parentheses to call this function
+   |
+LL |     do_on_foo(example());
+   |                      ++
+help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+   |
+LL |     do_on_foo(example as fn() -> bool);
+   |                       +++++++++++++++
+
+error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied
+  --> $DIR/fn-trait-cast-diagnostic.rs:24:22
+   |
+LL |     do_on_single_foo(example);
+   |     ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `do_on_single_foo`
+  --> $DIR/fn-trait-cast-diagnostic.rs:18:29
+   |
+LL | fn do_on_single_foo(v: impl NoOtherFoo) {}
+   |                             ^^^^^^^^^^ required by this bound in `do_on_single_foo`
+help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+   |
+LL |     do_on_single_foo(example as fn() -> bool);
+   |                              +++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr
index 4fe12731475..6b5b721384c 100644
--- a/tests/ui/traits/issue-43784-supertrait.stderr
+++ b/tests/ui/traits/issue-43784-supertrait.stderr
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL | impl<T> Complete for T {}
    |                      ^ the trait `Copy` is not implemented for `T`
    |
+note: required for `T` to implement `Partial`
+  --> $DIR/issue-43784-supertrait.rs:1:11
+   |
+LL | pub trait Partial: Copy {
+   |           ^^^^^^^
 note: required by a bound in `Complete`
   --> $DIR/issue-43784-supertrait.rs:4:21
    |
diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr
index 7924d3db06f..a11867c03a6 100644
--- a/tests/ui/traits/issue-52893.stderr
+++ b/tests/ui/traits/issue-52893.stderr
@@ -11,6 +11,13 @@ LL |         builder.push(output);
    |
    = note: expected type parameter `F`
                       found struct `Class<P>`
+help: the return type of this call is `Class<P>` due to the type of the argument passed
+  --> $DIR/issue-52893.rs:53:9
+   |
+LL |         builder.push(output);
+   |         ^^^^^^^^^^^^^------^
+   |                      |
+   |                      this argument influences the return type of `push`
 note: associated function defined here
   --> $DIR/issue-52893.rs:11:8
    |
diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr
index 3ff8f12f1b8..fb6eebbd254 100644
--- a/tests/ui/traits/issue-99875.stderr
+++ b/tests/ui/traits/issue-99875.stderr
@@ -6,12 +6,15 @@ LL |     takes(function);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
 note: required by a bound in `takes`
   --> $DIR/issue-99875.rs:9:18
    |
 LL | fn takes(_: impl Trait) {}
    |                  ^^^^^ required by this bound in `takes`
+help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as`
+   |
+LL |     takes(function as fn(Argument) -> Return);
+   |                    +++++++++++++++++++++++++
 
 error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
   --> $DIR/issue-99875.rs:14:11
diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs
new file mode 100644
index 00000000000..77e753c13f7
--- /dev/null
+++ b/tests/ui/traits/track-obligations.rs
@@ -0,0 +1,88 @@
+// These are simplifications of the tower traits by the same name:
+
+pub trait Service<Request> {
+    type Response;
+}
+
+pub trait Layer<C> {
+    type Service;
+}
+
+// Any type will do here:
+
+pub struct Req;
+pub struct Res;
+
+// This is encoding a trait alias.
+
+pub trait ParticularService:
+    Service<Req, Response = Res> {
+}
+
+impl<T> ParticularService for T
+where
+    T: Service<Req, Response = Res>,
+{
+}
+
+// This is also a trait alias.
+// The weird = <Self as ...> bound is there so that users of the trait do not
+// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671
+// for context, and in particular the workaround in:
+// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828
+
+pub trait ParticularServiceLayer<C>:
+    Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+{
+    type Service: ParticularService;
+}
+
+impl<T, C> ParticularServiceLayer<C> for T
+where
+    T: Layer<C>,
+    T::Service: ParticularService,
+{
+    type Service = T::Service;
+}
+
+// These are types that implement the traits that the trait aliases refer to.
+// They should also implement the alias traits due to the blanket impls.
+
+struct ALayer<C>(C);
+impl<C> Layer<C> for ALayer<C> {
+    type Service = AService;
+}
+
+struct AService;
+impl Service<Req> for AService {
+    // However, AService does _not_ meet the blanket implementation,
+    // since its Response type is bool, not Res as it should be.
+    type Response = bool;
+}
+
+// This is a wrapper type around ALayer that uses the trait alias
+// as a way to communicate the requirements of the provided types.
+struct Client<C>(C);
+
+// The method and the free-standing function below both have the same bounds.
+
+impl<C> Client<C>
+where
+    ALayer<C>: ParticularServiceLayer<C>,
+{
+    fn check(&self) {}
+}
+
+fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+
+// But, they give very different error messages.
+
+fn main() {
+    // This gives a very poor error message that does nothing to point the user
+    // at the underlying cause of why the types involved do not meet the bounds.
+    Client(()).check(); //~ ERROR E0599
+
+    // This gives a good(ish) error message that points the user at _why_ the
+    // bound isn't met, and thus how they might fix it.
+    check(()); //~ ERROR E0271
+}
diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr
new file mode 100644
index 00000000000..89477475970
--- /dev/null
+++ b/tests/ui/traits/track-obligations.stderr
@@ -0,0 +1,76 @@
+error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied
+  --> $DIR/track-obligations.rs:83:16
+   |
+LL | struct ALayer<C>(C);
+   | ----------------
+   | |
+   | doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service`
+   | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+...
+LL | struct Client<C>(C);
+   | ---------------- method `check` not found for this struct
+...
+LL |     Client(()).check();
+   |                ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
+   |
+note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
+  --> $DIR/track-obligations.rs:35:14
+   |
+LL | pub trait ParticularServiceLayer<C>:
+   |           ----------------------
+LL |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
+  --> $DIR/track-obligations.rs:71:16
+   |
+LL | impl<C> Client<C>
+   |         ---------
+LL | where
+LL |     ALayer<C>: ParticularServiceLayer<C>,
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: the trait `ParticularServiceLayer` must be implemented
+  --> $DIR/track-obligations.rs:34:1
+   |
+LL | / pub trait ParticularServiceLayer<C>:
+LL | |     Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+   | |____________________________________________________________________^
+
+error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
+  --> $DIR/track-obligations.rs:87:11
+   |
+LL |     check(());
+   |     ----- ^^ type mismatch resolving `<AService as Service<Req>>::Response == Res`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: expected this to be `Res`
+  --> $DIR/track-obligations.rs:60:21
+   |
+LL |     type Response = bool;
+   |                     ^^^^
+note: required for `AService` to implement `ParticularService`
+  --> $DIR/track-obligations.rs:22:9
+   |
+LL | impl<T> ParticularService for T
+   |         ^^^^^^^^^^^^^^^^^     ^
+LL | where
+LL |     T: Service<Req, Response = Res>,
+   |                     -------------- unsatisfied trait bound introduced here
+note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>`
+  --> $DIR/track-obligations.rs:40:12
+   |
+LL | impl<T, C> ParticularServiceLayer<C> for T
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+...
+LL |     T::Service: ParticularService,
+   |                 ----------------- unsatisfied trait bound introduced here
+note: required by a bound in `check`
+  --> $DIR/track-obligations.rs:76:36
+   |
+LL | fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0599.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs
new file mode 100644
index 00000000000..ba5b9f54246
--- /dev/null
+++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs
@@ -0,0 +1,28 @@
+fn function<T>(x: T, y: bool) -> T {
+    x
+}
+
+struct S {}
+impl S {
+    fn method<T>(&self, x: T) -> T {
+        x
+    }
+}
+
+fn wrong_arg_type(x: u32) -> u32 {
+    x
+}
+
+fn main() {
+    // Should not trigger.
+    let x = wrong_arg_type(0u16); //~ ERROR mismatched types
+    let x: u16 = function(0, 0u8); //~ ERROR mismatched types
+
+    // Should trigger exactly once for the first argument.
+    let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect
+
+    // Should trigger.
+    let x: u16 = function(0u32, true); //~ ERROR mismatched types
+    let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types
+    function(0u32, 8u8) //~ ERROR arguments to this function are incorrect
+}
diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr
new file mode 100644
index 00000000000..4d012cb156b
--- /dev/null
+++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr
@@ -0,0 +1,131 @@
+error[E0308]: mismatched types
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28
+   |
+LL |     let x = wrong_arg_type(0u16);
+   |             -------------- ^^^^ expected `u32`, found `u16`
+   |             |
+   |             arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4
+   |
+LL | fn wrong_arg_type(x: u32) -> u32 {
+   |    ^^^^^^^^^^^^^^ ------
+help: change the type of the numeric literal from `u16` to `u32`
+   |
+LL |     let x = wrong_arg_type(0u32);
+   |                             ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30
+   |
+LL |     let x: u16 = function(0, 0u8);
+   |                  --------    ^^^ expected `bool`, found `u8`
+   |                  |
+   |                  arguments to this function are incorrect
+   |
+note: function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+   |
+LL | fn function<T>(x: T, y: bool) -> T {
+   |    ^^^^^^^^          -------
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
+   |
+LL |     let x: u16 = function(0u32, 0u8);
+   |                  ^^^^^^^^ ----  --- expected `bool`, found `u8`
+   |                           |
+   |                           expected `u16`, found `u32`
+   |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
+   |
+LL |     let x: u16 = function(0u32, 0u8);
+   |                  ^^^^^^^^^----^^^^^^
+   |                           |
+   |                           this argument influences the return type of `function`
+note: function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+   |
+LL | fn function<T>(x: T, y: bool) -> T {
+   |    ^^^^^^^^    ----  -------
+help: change the type of the numeric literal from `u32` to `u16`
+   |
+LL |     let x: u16 = function(0u16, 0u8);
+   |                            ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27
+   |
+LL |     let x: u16 = function(0u32, true);
+   |                  -------- ^^^^ expected `u16`, found `u32`
+   |                  |
+   |                  arguments to this function are incorrect
+   |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18
+   |
+LL |     let x: u16 = function(0u32, true);
+   |                  ^^^^^^^^^----^^^^^^^
+   |                           |
+   |                           this argument influences the return type of `function`
+note: function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+   |
+LL | fn function<T>(x: T, y: bool) -> T {
+   |    ^^^^^^^^    ----
+help: change the type of the numeric literal from `u32` to `u16`
+   |
+LL |     let x: u16 = function(0u16, true);
+   |                            ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32
+   |
+LL |     let x: u16 = (S {}).method(0u32);
+   |                         ------ ^^^^ expected `u16`, found `u32`
+   |                         |
+   |                         arguments to this method are incorrect
+   |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18
+   |
+LL |     let x: u16 = (S {}).method(0u32);
+   |                  ^^^^^^^^^^^^^^----^
+   |                                |
+   |                                this argument influences the return type of `method`
+note: associated function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8
+   |
+LL |     fn method<T>(&self, x: T) -> T {
+   |        ^^^^^^           ----
+help: change the type of the numeric literal from `u32` to `u16`
+   |
+LL |     let x: u16 = (S {}).method(0u16);
+   |                                 ~~~
+
+error[E0308]: arguments to this function are incorrect
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
+   |
+LL |     function(0u32, 8u8)
+   |     ^^^^^^^^ ----  --- expected `bool`, found `u8`
+   |              |
+   |              expected `()`, found `u32`
+   |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
+   |
+LL |     function(0u32, 8u8)
+   |     ^^^^^^^^^----^^^^^^
+   |              |
+   |              this argument influences the return type of `function`
+note: function defined here
+  --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+   |
+LL | fn function<T>(x: T, y: bool) -> T {
+   |    ^^^^^^^^    ----  -------
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr
index f488463ae3c..8f5ff51fbe1 100644
--- a/tests/ui/typeck/issue-46112.stderr
+++ b/tests/ui/typeck/issue-46112.stderr
@@ -8,6 +8,13 @@ LL | fn main() { test(Ok(())); }
    |
    = note:   expected enum `Option<()>`
            found unit type `()`
+help: the type constructed contains `()` due to the type of the argument passed
+  --> $DIR/issue-46112.rs:9:18
+   |
+LL | fn main() { test(Ok(())); }
+   |                  ^^^--^
+   |                     |
+   |                     this argument influences the type of `Ok`
 note: tuple variant defined here
   --> $SRC_DIR/core/src/result.rs:LL:COL
 help: try wrapping the expression in `Some`
diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr
index 00d23389720..09f3aee2d9e 100644
--- a/tests/ui/typeck/issue-84768.stderr
+++ b/tests/ui/typeck/issue-84768.stderr
@@ -14,6 +14,13 @@ LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
    |
    = note: expected tuple `(&mut u8,)`
                found type `{integer}`
+help: the return type of this call is `{integer}` due to the type of the argument passed
+  --> $DIR/issue-84768.rs:7:5
+   |
+LL |     <F as FnOnce(&mut u8)>::call_once(f, 1)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
+   |                                          |
+   |                                          this argument influences the return type of `FnOnce`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
 
diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index a2fe627868a..e85144a31ca 100644
--- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -21,6 +21,13 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
    |     |
    |     arguments to this function are incorrect
    |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/ufcs-qpath-self-mismatch.rs:7:5
+   |
+LL |     <i32 as Add<i32>>::add(1u32, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^----^^^^
+   |                            |
+   |                            this argument influences the return type of `Add`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: change the type of the numeric literal from `u32` to `i32`
@@ -36,6 +43,13 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
    |     |
    |     arguments to this function are incorrect
    |
+help: the return type of this call is `u32` due to the type of the argument passed
+  --> $DIR/ufcs-qpath-self-mismatch.rs:9:5
+   |
+LL |     <i32 as Add<i32>>::add(1, 2u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^----^
+   |                               |
+   |                               this argument influences the return type of `Add`
 note: associated function defined here
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: change the type of the numeric literal from `u32` to `i32`
diff --git a/triagebot.toml b/triagebot.toml
index 914b52cf041..14bade6472f 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -251,7 +251,7 @@ new_pr = true
 
 [autolabel."WG-trait-system-refactor"]
 trigger_files = [
-    "compiler/rustc_trait_selection/solve"
+    "compiler/rustc_trait_selection/src/solve"
 ]
 
 [notify-zulip."I-prioritize"]