From 34ea540720828538d858cf66cc8473bb2f54e713 Mon Sep 17 00:00:00 2001
From: asquared31415 <34665709+asquared31415@users.noreply.github.com>
Date: Mon, 2 Oct 2023 15:10:51 +0000
Subject: [PATCH 1/7] add must_use on pointer equality functions

---
 library/core/src/ptr/mod.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index fe3d46d77f0da..5cd2a30331068 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1864,6 +1864,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 /// ```
 #[stable(feature = "ptr_eq", since = "1.17.0")]
 #[inline(always)]
+#[must_use = "pointer comparison produces a value"]
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
@@ -1886,6 +1887,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 /// ```
 #[unstable(feature = "ptr_addr_eq", issue = "116324")]
 #[inline(always)]
+#[must_use = "pointer comparison produces a value"]
 pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
     (p as *const ()) == (q as *const ())
 }

From 07e96314ec1ea2cd28f10224a90f1647e3082515 Mon Sep 17 00:00:00 2001
From: Orson Peters <orsonpeters@gmail.com>
Date: Mon, 2 Oct 2023 22:05:17 +0200
Subject: [PATCH 2/7] Clarify float rounding direction for signed zero

---
 library/core/src/primitive_docs.rs | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index fd5fe5a04f4d9..380a21b376bde 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1142,10 +1142,9 @@ impl<T: Copy> Copy for (T,) {
 ///     surprising results upon inspecting the bit patterns,
 ///     as the same calculations might produce NaNs with different bit patterns.
 ///
-/// When the number resulting from a primitive operation (addition,
-/// subtraction, multiplication, or division) on this type is not exactly
-/// representable as `f32`, it is rounded according to the roundTiesToEven
-/// direction defined in IEEE 754-2008. That means:
+/// When a primitive operation (addition, subtraction, multiplication, or
+/// division) is performed on this type, the result is rounded according to the
+/// roundTiesToEven direction defined in IEEE 754-2008. That means:
 ///
 /// - The result is the representable value closest to the true value, if there
 ///   is a unique closest representable value.
@@ -1154,6 +1153,9 @@ impl<T: Copy> Copy for (T,) {
 /// - If the true value's magnitude is ≥ `f32::MAX` + 2<sup>(`f32::MAX_EXP` −
 ///   `f32::MANTISSA_DIGITS` − 1)</sup>, the result is ∞ or −∞ (preserving the
 ///   true value's sign).
+/// - If the result of a sum exactly equals zero, the outcome is +0.0 unless
+///   both arguments were negative, then it is -0.0. Subtraction `a - b` is
+///   regarded as a sum `a + (-b)`.
 ///
 /// For more information on floating point numbers, see [Wikipedia][wikipedia].
 ///

From ac5aa8c1a4370b34674d18ef20b642645d2172e0 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Mon, 25 Sep 2023 18:57:12 +0000
Subject: [PATCH 3/7] Don't suggest nonsense suggestions for unconstrained type
 vars in note_source_of_type_mismatch_constraint

---
 compiler/rustc_hir_typeck/src/demand.rs        | 10 ++++++++--
 .../point-at-inference-issue-116155.rs         | 17 +++++++++++++++++
 .../point-at-inference-issue-116155.stderr     | 18 ++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/type/type-check/point-at-inference-issue-116155.rs
 create mode 100644 tests/ui/type/type-check/point-at-inference-issue-116155.stderr

diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d97691369c958..5c3f2b85966a8 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
+use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt as _;
@@ -504,12 +504,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // incompatible fix at the original mismatch site.
                     if matches!(source, TypeMismatchSource::Ty(_))
                         && let Some(ideal_method) = ideal_method
+                        && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1])
+                        // HACK(compiler-errors): We don't actually consider the implications
+                        // of our inference guesses in `emit_type_mismatch_suggestions`, so
+                        // only suggest things when we know our type error is precisely due to
+                        // a type mismatch, and not via some projection or something. See #116155.
+                        && !ideal_arg_ty.has_non_region_infer()
                     {
                         self.emit_type_mismatch_suggestions(
                             err,
                             arg_expr,
                             arg_ty,
-                            self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]),
+                            ideal_arg_ty,
                             None,
                             None,
                         );
diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.rs b/tests/ui/type/type-check/point-at-inference-issue-116155.rs
new file mode 100644
index 0000000000000..1e9942d42e867
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-issue-116155.rs
@@ -0,0 +1,17 @@
+struct S<T>(T);
+
+impl<T> S<T> {
+    fn new() -> Self {
+        loop {}
+    }
+
+    fn constrain<F: Fn() -> T>(&self, _f: F) {}
+}
+
+fn main() {
+    let s = S::new();
+    let c = || true;
+    s.constrain(c);
+    let _: S<usize> = s;
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/type/type-check/point-at-inference-issue-116155.stderr b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr
new file mode 100644
index 0000000000000..c8c01603cb848
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-issue-116155.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/point-at-inference-issue-116155.rs:15:23
+   |
+LL |     s.constrain(c);
+   |     -           - this argument has type `{closure@$DIR/point-at-inference-issue-116155.rs:13:13: 13:15}`...
+   |     |
+   |     ... which causes `s` to have type `S<bool>`
+LL |     let _: S<usize> = s;
+   |            --------   ^ expected `S<usize>`, found `S<bool>`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `S<usize>`
+              found struct `S<bool>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.

From f2918b4a3d4a36e0cca5dde4247817ef48af4c1f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io>
Date: Mon, 2 Oct 2023 23:43:35 +0200
Subject: [PATCH 4/7] Bump stdarch submodule

---
 library/core/src/lib.rs | 1 +
 library/stdarch         | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index be734a9ba5298..ab8d9f33b08b4 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -418,6 +418,7 @@ pub mod primitive;
 // FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
 // merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
 #[allow(clashing_extern_declarations)]
+#[cfg_attr(bootstrap, allow(deprecated_in_future))]
 #[unstable(feature = "stdsimd", issue = "48556")]
 mod core_arch;
 
diff --git a/library/stdarch b/library/stdarch
index 6100854c4b360..333e9e9977188 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit 6100854c4b360f84da5ab25e7c75cb2080667ddc
+Subproject commit 333e9e9977188d0748327e9b5be0f3f412063174

From 8be12f4ed70c55652fefdec63d094974d00e164c Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 10 Sep 2023 03:21:52 +0000
Subject: [PATCH 5/7] For a single impl candidate, try to unify it with error
 trait ref

---
 .../src/traits/error_reporting/mod.rs         | 78 ++++++++++++++++++-
 .../occurs-check/unused-substs-1.stderr       |  2 +-
 tests/ui/impl-trait/issues/issue-62742.stderr |  4 +-
 tests/ui/indexing/index-help.stderr           |  2 +-
 .../indexing/indexing-requires-a-uint.stderr  |  2 +-
 tests/ui/integral-indexing.stderr             | 16 ++--
 tests/ui/issues/issue-34334.stderr            |  2 +-
 ...e-66923-show-error-for-correct-call.stderr |  4 +-
 .../iterators/invalid-iterator-chain.stderr   |  4 +-
 tests/ui/on-unimplemented/impl-substs.stderr  |  2 +-
 tests/ui/on-unimplemented/slice-index.stderr  |  2 +-
 tests/ui/str/str-idx.stderr                   |  6 +-
 tests/ui/str/str-mut-idx.stderr               |  6 +-
 tests/ui/suggestions/issue-101623.stderr      |  2 +-
 .../suggest-dereferencing-index.stderr        |  2 +-
 tests/ui/try-trait/bad-interconversion.stderr |  6 +-
 16 files changed, 106 insertions(+), 34 deletions(-)

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 2a586f810d629..1a89f7b54e1f6 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -67,6 +67,7 @@ pub enum CandidateSimilarity {
 pub struct ImplCandidate<'tcx> {
     pub trait_ref: ty::TraitRef<'tcx>,
     pub similarity: CandidateSimilarity,
+    impl_def_id: DefId,
 }
 
 enum GetSafeTransmuteErrorAndReason {
@@ -1331,6 +1332,7 @@ trait InferCtxtPrivExt<'tcx> {
         body_def_id: LocalDefId,
         err: &mut Diagnostic,
         other: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> bool;
 
     fn report_similar_impl_candidates_for_root_obligation(
@@ -1918,8 +1920,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder();
 
-                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
-                    .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
+                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
+                    |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
+                )
             })
             .collect();
         if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) {
@@ -1938,7 +1941,71 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         body_def_id: LocalDefId,
         err: &mut Diagnostic,
         other: bool,
+        param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
+        if let [single] = &impl_candidates {
+            if self.probe(|_| {
+                let ocx = ObligationCtxt::new(self);
+                let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
+                let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
+                let impl_trait_ref = ocx.normalize(
+                    &ObligationCause::dummy(),
+                    param_env,
+                    ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args),
+                );
+
+                ocx.register_obligations(
+                    self.tcx
+                        .predicates_of(single.impl_def_id)
+                        .instantiate(self.tcx, impl_args)
+                        .into_iter()
+                        .map(|(clause, _)| {
+                            Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
+                        }),
+                );
+                if !ocx.select_where_possible().is_empty() {
+                    return false;
+                }
+
+                let mut terrs = vec![];
+                for (obligation_arg, impl_arg) in
+                    std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
+                {
+                    if let Err(terr) =
+                        ocx.eq(&ObligationCause::dummy(), param_env, obligation_arg, impl_arg)
+                    {
+                        terrs.push(terr);
+                    }
+                    if !ocx.select_where_possible().is_empty() {
+                        return false;
+                    }
+                }
+
+                // Literally nothing unified, just give up.
+                if terrs.len() == impl_trait_ref.args.len() {
+                    return false;
+                }
+
+                let cand =
+                    self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
+                        tcx: self.tcx,
+                        ty_op: |ty| ty,
+                        lt_op: |lt| lt,
+                        ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
+                    });
+                err.highlighted_help(vec![
+                    (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
+                    ("is".to_string(), Style::Highlight),
+                    (" implemented for `".to_string(), Style::NoStyle),
+                    (cand.self_ty().to_string(), Style::Highlight),
+                    ("`".to_string(), Style::NoStyle),
+                ]);
+                true
+            }) {
+                return true;
+            }
+        }
+
         let other = if other { "other " } else { "" };
         let report = |candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
             if candidates.is_empty() {
@@ -2062,9 +2129,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             })
             .collect();
         impl_candidates.sort_by_key(|cand| (cand.similarity, cand.trait_ref));
+        let mut impl_candidates: Vec<_> =
+            impl_candidates.into_iter().map(|cand| cand.trait_ref).collect();
         impl_candidates.dedup();
 
-        report(impl_candidates.into_iter().map(|cand| cand.trait_ref).collect(), err)
+        report(impl_candidates, err)
     }
 
     fn report_similar_impl_candidates_for_root_obligation(
@@ -2108,6 +2177,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 body_def_id,
                 err,
                 true,
+                obligation.param_env,
             );
         }
     }
@@ -2316,6 +2386,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             obligation.cause.body_id,
                             &mut err,
                             false,
+                            obligation.param_env,
                         );
                     }
                 }
@@ -3051,6 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 body_def_id,
                 err,
                 true,
+                obligation.param_env,
             ) {
                 self.report_similar_impl_candidates_for_root_obligation(
                     &obligation,
diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
index 51ef354e3ed4a..61d055e808473 100644
--- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
+++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
 LL |     let _ = A;
    |             ^ the trait `Bar<_>` is not implemented for `A<_>`
    |
-   = help: the trait `Bar<N>` is implemented for `A<7>`
+   = help: the trait `Bar<_>` is implemented for `A<7>`
 note: required by a bound in `A`
   --> $DIR/unused-substs-1.rs:9:11
    |
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index d872291c87054..7592a85068297 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
 LL |     WrongImpl::foo(0i32);
    |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
    |
-   = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
+   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:26:35
    |
@@ -42,7 +42,7 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
 LL |     WrongImpl::<()>::foo(0i32);
    |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
    |
-   = help: the trait `Raw<[T]>` is implemented for `RawImpl<T>`
+   = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:26:35
    |
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index e020d0298757d..d3310ceb0537a 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -5,7 +5,7 @@ LL |     x[0i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to previous error
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index 7a741cfc7def4..fcfac3a5e93e7 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -5,7 +5,7 @@ LL |     [0][0u8];
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = note: required for `[{integer}]` to implement `Index<u8>`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index bbbb2a86a22da..b7d80565a1e61 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -5,7 +5,7 @@ LL |     v[3u8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -15,7 +15,7 @@ LL |     v[3i8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -25,7 +25,7 @@ LL |     v[3u32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -35,7 +35,7 @@ LL |     v[3i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -45,7 +45,7 @@ LL |     s.as_bytes()[3u8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -55,7 +55,7 @@ LL |     s.as_bytes()[3i8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -65,7 +65,7 @@ LL |     s.as_bytes()[3u32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -75,7 +75,7 @@ LL |     s.as_bytes()[3i32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
    = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr
index 9d2c315e4dbca..bacae965eed83 100644
--- a/tests/ui/issues/issue-34334.stderr
+++ b/tests/ui/issues/issue-34334.stderr
@@ -19,7 +19,7 @@ LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
    |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-34334.rs:5:43
    |
diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
index 22b1da64cb315..48cd549cb3344 100644
--- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -5,7 +5,7 @@ LL |     let x2: Vec<f64> = x1.into_iter().collect();
    |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
    |
@@ -25,7 +25,7 @@ LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
    |                             required by a bound introduced by this call
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
    |
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index b355da5cb768e..1d7cf03997261 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -5,7 +5,7 @@ LL |     i.collect()
    |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
    |
    = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<X>` is implemented for `Vec<X>`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:4:26
    |
@@ -159,7 +159,7 @@ LL |     let g: Vec<i32> = f.collect();
    |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
-   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
+   = help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:44:15
    |
diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr
index a0fad0acd0b5c..018068c1af1b4 100644
--- a/tests/ui/on-unimplemented/impl-substs.stderr
+++ b/tests/ui/on-unimplemented/impl-substs.stderr
@@ -7,7 +7,7 @@ LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
    |     required by a bound introduced by this call
    |
    = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
-   = help: the trait `Foo<A>` is implemented for `(A, B, C)`
+   = help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index b9bca211f438b..d378470a36885 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -5,7 +5,7 @@ LL |     x[1i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[i32]>` is implemented for `usize`
    = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index cb1a6fcacfc9b..3b4cb5e6a190b 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -7,7 +7,7 @@ LL |     let _: u8 = s[4];
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
    = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -21,7 +21,7 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -36,7 +36,7 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index ca4b86ba3065b..f22ecea625770 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -31,7 +31,7 @@ LL |     s[1usize] = bot();
    |       ^^^^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
    = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -45,7 +45,7 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -60,7 +60,7 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr
index 361483cc08db2..cfb5c6ae1917e 100644
--- a/tests/ui/suggestions/issue-101623.stderr
+++ b/tests/ui/suggestions/issue-101623.stderr
@@ -7,7 +7,7 @@ LL |     Trait::do_stuff({ fun(&mut *inner) });
    |     |               the trait `Trait<'_>` is not implemented for `*mut ()`
    |     required by a bound introduced by this call
    |
-   = help: the trait `Trait<'a>` is implemented for `()`
+   = help: the trait `Trait<'_>` is implemented for `()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 147dc9234c598..47cb25de627d3 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -5,7 +5,7 @@ LL |     let one_item_please: i32 = [1, 2, 3][i];
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
-   = help: the trait `SliceIndex<[T]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
    = note: required for `[{integer}]` to implement `Index<&usize>`
 help: dereference this index
    |
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 7eb392faa66b3..7039a5c5495a9 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -73,7 +73,7 @@ LL |     ControlFlow::Continue(Err("hello")?)
    |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<String, Infallible>>` is implemented for `ControlFlow<String>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:37:12
@@ -84,7 +84,7 @@ LL |     Some(3)?;
    |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<u64, Infallible>>` is implemented for `ControlFlow<u64>`
 
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
   --> $DIR/bad-interconversion.rs:43:29
@@ -96,7 +96,7 @@ LL |     ControlFlow::Break(4_u8)?;
    |
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
-   = help: the trait `FromResidual` is implemented for `ControlFlow<B, C>`
+   = help: the trait `FromResidual<ControlFlow<i64, Infallible>>` is implemented for `ControlFlow<i64>`
 
 error: aborting due to 8 previous errors
 

From 07851679cd8ced5933095c4173d3877c1abc96dd Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 10 Sep 2023 03:33:07 +0000
Subject: [PATCH 6/7] Point out the actual mismatch error

---
 .../src/traits/error_reporting/mod.rs             | 15 ++++++++++++++-
 .../generic-const-items/unsatisfied-bounds.stderr |  2 ++
 tests/ui/impl-trait/issues/issue-62742.stderr     |  1 +
 tests/ui/indexing/index-help.stderr               |  1 +
 tests/ui/indexing/indexing-requires-a-uint.stderr |  1 +
 tests/ui/integral-indexing.stderr                 |  8 ++++++++
 tests/ui/issues/issue-34334.stderr                |  1 +
 tests/ui/issues/issue-45801.stderr                |  1 +
 ...issue-66923-show-error-for-correct-call.stderr |  2 ++
 tests/ui/iterators/invalid-iterator-chain.stderr  |  2 ++
 ...r-value-fallback-issue-66757.nofallback.stderr |  1 +
 tests/ui/on-unimplemented/impl-substs.stderr      |  1 +
 tests/ui/on-unimplemented/on-impl.stderr          |  3 +++
 tests/ui/on-unimplemented/slice-index.stderr      |  1 +
 tests/ui/str/str-idx.stderr                       |  3 +++
 tests/ui/str/str-mut-idx.stderr                   |  3 +++
 tests/ui/suggestions/issue-101623.stderr          |  1 +
 .../suggest-dereferencing-index.stderr            |  1 +
 tests/ui/traits/coercion-generic-bad.stderr       |  1 +
 tests/ui/try-block/try-block-bad-type.stderr      |  1 +
 tests/ui/try-trait/bad-interconversion.stderr     |  3 +++
 21 files changed, 52 insertions(+), 1 deletion(-)

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 1a89f7b54e1f6..9a728b1060fb1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength :(
+
 mod ambiguity;
 pub mod on_unimplemented;
 pub mod suggestions;
@@ -1943,6 +1945,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         other: bool,
         param_env: ty::ParamEnv<'tcx>,
     ) -> bool {
+        // If we have a single implementation, try to unify it with the trait ref
+        // that failed. This should uncover a better hint for what *is* implemented.
         if let [single] = &impl_candidates {
             if self.probe(|_| {
                 let ocx = ObligationCtxt::new(self);
@@ -1972,7 +1976,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args)
                 {
                     if let Err(terr) =
-                        ocx.eq(&ObligationCause::dummy(), param_env, obligation_arg, impl_arg)
+                        ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg)
                     {
                         terrs.push(terr);
                     }
@@ -2000,6 +2004,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     (cand.self_ty().to_string(), Style::Highlight),
                     ("`".to_string(), Style::NoStyle),
                 ]);
+
+                if let [TypeError::Sorts(exp_found)] = &terrs[..] {
+                    let exp_found = self.resolve_vars_if_possible(*exp_found);
+                    err.help(format!(
+                        "for that trait implementation, expected `{}`, found `{}`",
+                        exp_found.expected, exp_found.found
+                    ));
+                }
+
                 true
             }) {
                 return true;
diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
index 2cee53431a42e..14894cef77089 100644
--- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr
+++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
@@ -17,6 +17,7 @@ LL |     let () = K::<()>;
    |                  ^^ the trait `From<()>` is not implemented for `Infallible`
    |
    = help: the trait `From<!>` is implemented for `Infallible`
+   = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `K`
   --> $DIR/unsatisfied-bounds.rs:12:17
    |
@@ -48,6 +49,7 @@ LL |     let _ = <() as Trait<&'static str>>::B::<()>;
    |                                              ^^ the trait `From<()>` is not implemented for `Infallible`
    |
    = help: the trait `From<!>` is implemented for `Infallible`
+   = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `Trait::B`
   --> $DIR/unsatisfied-bounds.rs:21:21
    |
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index 7592a85068297..8d969e8e0f3dc 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -43,6 +43,7 @@ LL |     WrongImpl::<()>::foo(0i32);
    |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
    |
    = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
+   = help: for that trait implementation, expected `[()]`, found `()`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:26:35
    |
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index d3310ceb0537a..2cb212a013960 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -6,6 +6,7 @@ LL |     x[0i32];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to previous error
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index fcfac3a5e93e7..6ea6bb600e944 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -6,6 +6,7 @@ LL |     [0][0u8];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[{integer}]` to implement `Index<u8>`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index b7d80565a1e61..97e658617cf03 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -6,6 +6,7 @@ LL |     v[3u8];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -16,6 +17,7 @@ LL |     v[3i8];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -26,6 +28,7 @@ LL |     v[3u32];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -36,6 +39,7 @@ LL |     v[3i32];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -46,6 +50,7 @@ LL |     s.as_bytes()[3u8];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -56,6 +61,7 @@ LL |     s.as_bytes()[3i8];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -66,6 +72,7 @@ LL |     s.as_bytes()[3u32];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -76,6 +83,7 @@ LL |     s.as_bytes()[3i32];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr
index bacae965eed83..753942dd1d189 100644
--- a/tests/ui/issues/issue-34334.stderr
+++ b/tests/ui/issues/issue-34334.stderr
@@ -20,6 +20,7 @@ LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
+   = help: for that trait implementation, expected `(u32, _, _)`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-34334.rs:5:43
    |
diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr
index 8967f49df02a5..e651e2a68d160 100644
--- a/tests/ui/issues/issue-45801.stderr
+++ b/tests/ui/issues/issue-45801.stderr
@@ -5,6 +5,7 @@ LL |     req.get_ref::<Params>();
    |         ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params`
    |
    = help: the trait `Plugin<Foo>` is implemented for `Params`
+   = help: for that trait implementation, expected `Foo`, found `i32`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
index 48cd549cb3344..128288e28f5ac 100644
--- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -6,6 +6,7 @@ LL |     let x2: Vec<f64> = x1.into_iter().collect();
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
    |
@@ -26,6 +27,7 @@ LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
    |
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index 1d7cf03997261..2601c9c0d69d3 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -6,6 +6,7 @@ LL |     i.collect()
    |
    = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
    = help: the trait `FromIterator<X>` is implemented for `Vec<X>`
+   = help: for that trait implementation, expected `X`, found `&X`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:4:26
    |
@@ -160,6 +161,7 @@ LL |     let g: Vec<i32> = f.collect();
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
    = help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
+   = help: for that trait implementation, expected `i32`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:44:15
    |
diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
index 54c16230fe68b..cb37863058931 100644
--- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
+++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -5,6 +5,7 @@ LL |     <E as From<_>>::from(never);
    |      ^ the trait `From<()>` is not implemented for `E`
    |
    = help: the trait `From<!>` is implemented for `E`
+   = help: for that trait implementation, expected `!`, found `()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr
index 018068c1af1b4..36d80f3e681bb 100644
--- a/tests/ui/on-unimplemented/impl-substs.stderr
+++ b/tests/ui/on-unimplemented/impl-substs.stderr
@@ -8,6 +8,7 @@ LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
    |
    = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
    = help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
+   = help: for that trait implementation, expected `i32`, found `usize`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr
index 2253c5992a64a..3a0b8353fa5eb 100644
--- a/tests/ui/on-unimplemented/on-impl.stderr
+++ b/tests/ui/on-unimplemented/on-impl.stderr
@@ -8,6 +8,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
@@ -17,6 +18,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:5
@@ -26,6 +28,7 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
    = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: for that trait implementation, expected `usize`, found `u32`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index d378470a36885..5e0117be5295c 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -6,6 +6,7 @@ LL |     x[1i32];
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[i32]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index 3b4cb5e6a190b..e8bbb8058faf3 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -8,6 +8,7 @@ LL |     let _: u8 = s[4];
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -22,6 +23,7 @@ LL |     let _ = s.get(4);
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -37,6 +39,7 @@ LL |     let _ = s.get_unchecked(4);
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index f22ecea625770..e6835bb54fb3d 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -32,6 +32,7 @@ LL |     s[1usize] = bot();
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -46,6 +47,7 @@ LL |     s.get_mut(1);
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -61,6 +63,7 @@ LL |     s.get_unchecked_mut(1);
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr
index cfb5c6ae1917e..9f00de17484fb 100644
--- a/tests/ui/suggestions/issue-101623.stderr
+++ b/tests/ui/suggestions/issue-101623.stderr
@@ -8,6 +8,7 @@ LL |     Trait::do_stuff({ fun(&mut *inner) });
    |     required by a bound introduced by this call
    |
    = help: the trait `Trait<'_>` is implemented for `()`
+   = help: for that trait implementation, expected `()`, found `*mut ()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 47cb25de627d3..adf01339972e5 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -6,6 +6,7 @@ LL |     let one_item_please: i32 = [1, 2, 3][i];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
    = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: for that trait implementation, expected `usize`, found `&usize`
    = note: required for `[{integer}]` to implement `Index<&usize>`
 help: dereference this index
    |
diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr
index e7e8a796796b3..30a3c40db95b3 100644
--- a/tests/ui/traits/coercion-generic-bad.stderr
+++ b/tests/ui/traits/coercion-generic-bad.stderr
@@ -5,6 +5,7 @@ LL |     let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
    |
    = help: the trait `Trait<&'static str>` is implemented for `Struct`
+   = help: for that trait implementation, expected `&'static str`, found `isize`
    = note: required for the cast from `Box<Struct>` to `Box<dyn Trait<isize>>`
 
 error: aborting due to previous error
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index e11c3f810035c..b41bf86d3d911 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -6,6 +6,7 @@ LL |         Err("")?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the trait `From<Infallible>` is implemented for `TryFromSliceError`
+   = help: for that trait implementation, expected `Infallible`, found `&str`
    = note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 7039a5c5495a9..d8b9431becc6b 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -74,6 +74,7 @@ LL |     ControlFlow::Continue(Err("hello")?)
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
    = help: the trait `FromResidual<ControlFlow<String, Infallible>>` is implemented for `ControlFlow<String>`
+   = help: for that trait implementation, expected `ControlFlow<String, Infallible>`, found `Result<Infallible, &str>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:37:12
@@ -85,6 +86,7 @@ LL |     Some(3)?;
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
    = help: the trait `FromResidual<ControlFlow<u64, Infallible>>` is implemented for `ControlFlow<u64>`
+   = help: for that trait implementation, expected `ControlFlow<u64, Infallible>`, found `Option<Infallible>`
 
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
   --> $DIR/bad-interconversion.rs:43:29
@@ -97,6 +99,7 @@ LL |     ControlFlow::Break(4_u8)?;
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
    = help: the trait `FromResidual<ControlFlow<i64, Infallible>>` is implemented for `ControlFlow<i64>`
+   = help: for that trait implementation, expected `i64`, found `u8`
 
 error: aborting due to 8 previous errors
 

From df911dfdd620cb0660e8c08857dc9b5e402946b6 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 26 Jun 2023 13:03:35 +0200
Subject: [PATCH 7/7] add notes about non-compliant FP behavior on 32bit x86
 targets

---
 src/doc/rustc/src/platform-support.md | 47 +++++++++++++++------------
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index ff831a2050480..ef4eb5a196576 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,9 +33,9 @@ All tier 1 targets with host tools support the full standard library.
 target | notes
 -------|-------
 `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes]
-`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support]
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support]
-`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+)
+`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
 `x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+)
 `x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support]
 `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support]
@@ -47,7 +47,10 @@ target | notes
 
 [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community.
 
+[^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
+
 [77071]: https://github.com/rust-lang/rust/issues/77071
+[x86-32-float-issue]: https://github.com/rust-lang/rust/issues/114479
 
 ## Tier 1
 
@@ -150,12 +153,12 @@ target | std | notes
 `armv7r-none-eabi` | * | Bare ARMv7-R
 `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat
 `asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten
-`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE
-`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17)
-`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL
-[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
-`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
-`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
+`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87]
+`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87]
+`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87]
+[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
+`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
+`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI]
 [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
 [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
 [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
@@ -195,6 +198,8 @@ target | std | notes
 `x86_64-unknown-redox` | ✓ | Redox OS
 [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
 
+[^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue].
+
 [Fortanix ABI]: https://edp.fortanix.com/
 
 ## Tier 3
@@ -264,18 +269,18 @@ target | std | host | notes
 `bpfel-unknown-none` | * |  | BPF (little endian)
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux(little endian)
 `hexagon-unknown-linux-musl` | ? |  |
-`i386-apple-ios` | ✓ |  | 32-bit x86 iOS
-[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS |
-`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+)
-`i686-pc-windows-msvc` | * |  | 32-bit Windows XP support
-[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
-`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
-[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd
-[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2
-[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
-`i686-uwp-windows-gnu` | ? |  |
-`i686-uwp-windows-msvc` | ? |  |
-`i686-wrs-vxworks` | ? |  |
+`i386-apple-ios` | ✓ |  | 32-bit x86 iOS [^x86_32-floats-return-ABI]
+[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS  [^x86_32-floats-return-ABI]
+`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | * |  | 32-bit Windows XP support [^x86_32-floats-return-ABI]
+[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI]
+`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI]
+[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
+[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
+[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
+`i686-uwp-windows-gnu` | ? |  | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-msvc` | ? |  | [^x86_32-floats-return-ABI]
+`i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL