From ef212e7fb306626b4dc2c484aa3cf3b42a83e83a Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Fri, 1 Oct 2021 13:05:17 +0000
Subject: [PATCH 1/2] Point at overlapping impls when type annotations are
 needed

---
 compiler/rustc_middle/src/traits/mod.rs       |  12 ++
 .../src/traits/error_reporting/mod.rs         | 163 ++++++++++++++-
 .../src/traits/error_reporting/suggestions.rs |  21 +-
 .../src/traits/select/candidate_assembly.rs   |  12 +-
 .../src/traits/select/mod.rs                  |  23 +-
 .../src/traits/specialize/mod.rs              |   2 +-
 compiler/rustc_typeck/src/check/coercion.rs   |   5 +-
 .../coherence-overlap-trait-alias.stderr      |   9 +-
 src/test/ui/error-codes/E0283.stderr          |   9 +-
 src/test/ui/impl-trait/equality.rs            |   2 +-
 src/test/ui/impl-trait/equality.stderr        |  19 +-
 src/test/ui/inference/issue-71732.stderr      |   5 +-
 src/test/ui/inference/issue-72616.stderr      |   6 +-
 src/test/ui/issues/issue-29147.stderr         |   8 +-
 src/test/ui/issues/issue-69455.rs             |   1 +
 src/test/ui/issues/issue-69455.stderr         |  24 ++-
 src/test/ui/issues/issue-69683.rs             |   1 +
 src/test/ui/issues/issue-69683.stderr         |  20 +-
 src/test/ui/issues/issue-72690.rs             |   9 +
 src/test/ui/issues/issue-72690.stderr         | 197 ++++++++++++++++--
 .../marker_trait_attr/region-overlap.stderr   |  16 +-
 ...method-ambig-one-trait-unknown-int-type.rs |   2 +-
 ...od-ambig-one-trait-unknown-int-type.stderr |  19 +-
 src/test/ui/traits/issue-77982.rs             |   1 +
 src/test/ui/traits/issue-77982.stderr         |  61 +++++-
 .../multidispatch-convert-ambig-dest.rs       |   3 +-
 .../multidispatch-convert-ambig-dest.stderr   |  31 ++-
 src/test/ui/traits/test-2.rs                  |   4 +-
 src/test/ui/traits/test-2.stderr              |  32 ++-
 29 files changed, 629 insertions(+), 88 deletions(-)

diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index b089ae22d6d..6570d8e1567 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -440,16 +440,28 @@ pub struct DerivedObligationCause<'tcx> {
 
 #[derive(Clone, Debug, TypeFoldable, Lift)]
 pub enum SelectionError<'tcx> {
+    /// The trait is not implemented.
     Unimplemented,
+    /// After a closure impl has selected, its "outputs" were evaluated
+    /// (which for closures includes the "input" type params) and they
+    /// didn't resolve. See `confirm_poly_trait_refs` for more.
     OutputTypeParameterMismatch(
         ty::PolyTraitRef<'tcx>,
         ty::PolyTraitRef<'tcx>,
         ty::error::TypeError<'tcx>,
     ),
+    /// The trait pointed by `DefId` is not object safe.
     TraitNotObjectSafe(DefId),
+    /// A given constant couldn't be evaluated.
     NotConstEvaluatable(NotConstEvaluatable),
+    /// Exceeded the recursion depth during type projection.
     Overflow,
+    /// Signaling that an error has already been emitted, to avoid
+    /// multiple errors being shown.
     ErrorReporting,
+    /// Multiple applicable `impl`s where found. The `DefId`s correspond to
+    /// all the `impl`s' Items.
+    Ambiguous(Vec<DefId>),
 }
 
 /// When performing resolution, it is typically the case that there
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 225ff5e597e..8396e3263f9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -34,6 +34,7 @@ use std::iter;
 
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::normalize::AtExt as _;
+use crate::traits::specialize::to_pretty_impl_header;
 use on_unimplemented::InferCtxtExt as _;
 use suggestions::InferCtxtExt as _;
 
@@ -241,6 +242,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let mut span = obligation.cause.span;
 
         let mut err = match *error {
+            SelectionError::Ambiguous(ref impls) => {
+                let mut err = self.tcx.sess.struct_span_err(
+                    obligation.cause.span,
+                    &format!("multiple applicable `impl`s for `{}`", obligation.predicate),
+                );
+                self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate);
+                err.emit();
+                return;
+            }
             SelectionError::Unimplemented => {
                 // If this obligation was generated as a result of well-formedness checking, see if we
                 // can get a better error message by performing HIR-based well-formedness checking.
@@ -1138,6 +1148,13 @@ trait InferCtxtPrivExt<'tcx> {
         obligation: &PredicateObligation<'tcx>,
     );
 
+    fn annotate_source_of_ambiguity(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        impls: &[DefId],
+        predicate: ty::Predicate<'tcx>,
+    );
+
     fn maybe_suggest_unsized_generics(
         &self,
         err: &mut DiagnosticBuilder<'tcx>,
@@ -1549,11 +1566,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             ?predicate, ?obligation.cause.code,
         );
 
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
+        // Ambiguity errors are often caused as fallout from earlier errors.
+        // We ignore them if this `infcx` is tainted in some cases below.
 
         let bound_predicate = predicate.kind();
         let mut err = match bound_predicate.skip_binder() {
@@ -1601,10 +1615,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
                 if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
-                    self.emit_inference_failure_err(body_id, span, subst, vec![], ErrorCode::E0282)
+                    if !self.is_tainted_by_errors() {
+                        self.emit_inference_failure_err(
+                            body_id,
+                            span,
+                            subst,
+                            vec![],
+                            ErrorCode::E0282,
+                        )
                         .emit();
+                    }
                     return;
                 }
+
                 let impl_candidates = self.find_similar_impl_candidates(trait_ref);
                 let mut err = self.emit_inference_failure_err(
                     body_id,
@@ -1613,7 +1636,29 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                     impl_candidates,
                     ErrorCode::E0283,
                 );
-                err.note(&format!("cannot satisfy `{}`", predicate));
+
+                let obligation = Obligation::new(
+                    obligation.cause.clone(),
+                    obligation.param_env,
+                    trait_ref.to_poly_trait_predicate(),
+                );
+                let mut selcx = SelectionContext::with_query_mode(
+                    &self,
+                    crate::traits::TraitQueryMode::Standard,
+                );
+                match selcx.select_from_obligation(&obligation) {
+                    Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => {
+                        self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                    }
+                    _ => {
+                        if self.is_tainted_by_errors() {
+                            err.cancel();
+                            return;
+                        }
+                        err.note(&format!("cannot satisfy `{}`", predicate));
+                    }
+                }
+
                 if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
                 } else if let (
@@ -1674,7 +1719,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             ty::PredicateKind::WellFormed(arg) => {
                 // Same hacky approach as above to avoid deluging user
                 // with error messages.
-                if arg.references_error() || self.tcx.sess.has_errors() {
+                if arg.references_error()
+                    || self.tcx.sess.has_errors()
+                    || self.is_tainted_by_errors()
+                {
                     return;
                 }
 
@@ -1682,7 +1730,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
 
             ty::PredicateKind::Subtype(data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
+                if data.references_error()
+                    || self.tcx.sess.has_errors()
+                    || self.is_tainted_by_errors()
+                {
                     // no need to overload user in such cases
                     return;
                 }
@@ -1694,7 +1745,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             ty::PredicateKind::Projection(data) => {
                 let self_ty = data.projection_ty.self_ty();
                 let ty = data.ty;
-                if predicate.references_error() {
+                if predicate.references_error() || self.is_tainted_by_errors() {
                     return;
                 }
                 if self_ty.needs_infer() && ty.needs_infer() {
@@ -1722,7 +1773,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
 
             _ => {
-                if self.tcx.sess.has_errors() {
+                if self.tcx.sess.has_errors() || self.is_tainted_by_errors() {
                     return;
                 }
                 let mut err = struct_span_err!(
@@ -1740,6 +1791,96 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         err.emit();
     }
 
+    fn annotate_source_of_ambiguity(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        impls: &[DefId],
+        predicate: ty::Predicate<'tcx>,
+    ) {
+        let mut spans = vec![];
+        let mut crates = vec![];
+        let mut post = vec![];
+        for def_id in impls {
+            match self.tcx.span_of_impl(*def_id) {
+                Ok(span) => spans.push(self.tcx.sess.source_map().guess_head_span(span)),
+                Err(name) => {
+                    crates.push(name);
+                    if let Some(header) = to_pretty_impl_header(self.tcx, *def_id) {
+                        post.push(header);
+                    }
+                }
+            }
+        }
+        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
+        crate_names.sort();
+        crate_names.dedup();
+        post.sort();
+        post.dedup();
+
+        if self.is_tainted_by_errors()
+            && crate_names.len() == 1
+            && crate_names[0] == "`core`"
+            && spans.len() == 0
+        {
+            // Avoid complaining about other inference issues for expressions like
+            // `42 >> 1`, where the types are still `{integer}`, but we want to
+            // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
+            err.cancel();
+            return;
+        }
+        let post = if post.len() > 4 {
+            format!(
+                ":\n{}\nand {} more",
+                post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
+                post.len() - 4,
+            )
+        } else if post.len() > 1 || (post.len() == 1 && post[0].contains("\n")) {
+            format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
+        } else if post.len() == 1 {
+            format!(": `{}`", post[0])
+        } else {
+            String::new()
+        };
+
+        match (spans.len(), crates.len(), crate_names.len()) {
+            (0, 0, 0) => {
+                err.note(&format!("cannot satisfy `{}`", predicate));
+            }
+            (0, _, 1) => {
+                err.note(&format!("{} in the `{}` crate{}", msg, crates[0], post,));
+            }
+            (0, _, _) => {
+                err.note(&format!(
+                    "{} in the following crates: {}{}",
+                    msg,
+                    crate_names.join(", "),
+                    post,
+                ));
+            }
+            (_, 0, 0) => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, &msg);
+            }
+            (_, 1, 1) => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, &msg);
+                err.note(
+                    &format!("and another `impl` found in the `{}` crate{}", crates[0], post,),
+                );
+            }
+            _ => {
+                let span: MultiSpan = spans.into();
+                err.span_note(span, &msg);
+                err.note(&format!(
+                    "and more `impl`s found in the following crates: {}{}",
+                    crate_names.join(", "),
+                    post,
+                ));
+            }
+        }
+    }
+
     /// Returns `true` if the trait predicate may apply for *some* assignment
     /// to the type parameters.
     fn predicate_can_apply(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 970fb304879..b4fd851f456 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -299,18 +299,15 @@ fn suggest_restriction(
                 generics,
                 trait_ref.without_const().to_predicate(tcx).to_string(),
             ),
-            (None, Some((ident, []))) => (
-                ident.span.shrink_to_hi(),
-                format!(": {}", trait_ref.print_only_trait_path().to_string()),
-            ),
-            (_, Some((_, [.., bounds]))) => (
-                bounds.span().shrink_to_hi(),
-                format!(" + {}", trait_ref.print_only_trait_path().to_string()),
-            ),
-            (Some(_), Some((_, []))) => (
-                generics.span.shrink_to_hi(),
-                format!(": {}", trait_ref.print_only_trait_path().to_string()),
-            ),
+            (None, Some((ident, []))) => {
+                (ident.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path()))
+            }
+            (_, Some((_, [.., bounds]))) => {
+                (bounds.span().shrink_to_hi(), format!(" + {}", trait_ref.print_only_trait_path()))
+            }
+            (Some(_), Some((_, []))) => {
+                (generics.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path()))
+            }
         };
 
         err.span_suggestion_verbose(
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e12b84742bf..1d0c54f86de 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -18,7 +18,7 @@ use crate::traits;
 use crate::traits::coherence::Conflict;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{util, SelectionResult};
-use crate::traits::{ErrorReporting, Overflow, Unimplemented};
+use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented};
 
 use super::BuiltinImplConditions;
 use super::IntercrateAmbiguityCause;
@@ -197,7 +197,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // and report ambiguity.
                     if i > 1 {
                         debug!("multiple matches, ambig");
-                        return Ok(None);
+                        return Err(Ambiguous(
+                            candidates
+                                .into_iter()
+                                .filter_map(|c| match c.candidate {
+                                    SelectionCandidate::ImplCandidate(def_id) => Some(def_id),
+                                    _ => None,
+                                })
+                                .collect(),
+                        ));
                     }
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 43ffa285b8f..1b26e38fe0e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -357,18 +357,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         obligation: &TraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>> {
-        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
-
-        let pec = &ProvisionalEvaluationCache::default();
-        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);
-
-        let candidate = match self.candidate_from_obligation(&stack) {
+        let candidate = match self.select_from_obligation(obligation) {
             Err(SelectionError::Overflow) => {
                 // In standard mode, overflow must have been caught and reported
                 // earlier.
                 assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow);
             }
+            Err(SelectionError::Ambiguous(_)) => {
+                return Ok(None);
+            }
             Err(e) => {
                 return Err(e);
             }
@@ -391,6 +389,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    crate fn select_from_obligation(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
+
+        let pec = &ProvisionalEvaluationCache::default();
+        let stack = self.push_stack(TraitObligationStackList::empty(pec), obligation);
+
+        self.candidate_from_obligation(&stack)
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // EVALUATION
     //
@@ -915,6 +925,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match self.candidate_from_obligation(stack) {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
+            Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow) => Err(OverflowError::Canonical),
             Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 88aca794a6b..f9867f0671e 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -464,7 +464,7 @@ fn report_conflicting_impls(
 
 /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
 /// string.
-fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
+crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
     use std::fmt::Write;
 
     let trait_ref = tcx.impl_trait_ref(impl_def_id)?;
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 40f456de183..ad65a0ba62a 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -185,9 +185,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 debug!("coerce: unsize not object safe");
                 return Err(TypeError::ObjectUnsafeCoercion(did));
             }
-            Err(_) => {}
+            Err(error) => {
+                debug!(?error, "coerce: unsize failed");
+            }
         }
-        debug!("coerce: unsize failed");
 
         // Examine the supertype and consider auto-borrowing.
         match *b.kind() {
diff --git a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
index e2e8ad54beb..affc58b84d4 100644
--- a/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
+++ b/src/test/ui/coherence/coherence-overlap-trait-alias.stderr
@@ -4,7 +4,14 @@ error[E0283]: type annotations needed
 LL | impl C for u32 {}
    |      ^ cannot infer type for type `u32`
    |
-   = note: cannot satisfy `u32: C`
+note: multiple `impl`s satisfying `u32: C` found
+  --> $DIR/coherence-overlap-trait-alias.rs:13:1
+   |
+LL | impl<T: AB> C for T {}
+   | ^^^^^^^^^^^^^^^^^^^
+LL | #[rustc_strict_coherence]
+LL | impl C for u32 {}
+   | ^^^^^^^^^^^^^^
 note: required by a bound in `C`
   --> $DIR/coherence-overlap-trait-alias.rs:11:1
    |
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index b6078e30236..95437bf11ad 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -21,7 +21,14 @@ LL |     let bar = foo_impl.into() * 1u32;
    |               this method call resolves to `T`
    |               help: use the fully qualified path for the potential candidate: `<Impl as Into<u32>>::into(foo_impl)`
    |
-   = note: cannot satisfy `Impl: Into<_>`
+note: multiple `impl`s satisfying `Impl: Into<_>` found
+  --> $DIR/E0283.rs:17:1
+   |
+LL | impl Into<u32> for Impl {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: and another `impl` found in the `core` crate:
+           - impl<T, U> Into<U> for T
+             where U: From<T>;
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
index 828b5aac896..9610618ca11 100644
--- a/src/test/ui/impl-trait/equality.rs
+++ b/src/test/ui/impl-trait/equality.rs
@@ -17,7 +17,7 @@ fn two(x: bool) -> impl Foo {
     //~| expected `i32`, found `u32`
 }
 
-fn sum_to(n: u32) -> impl Foo {
+fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed
     if n == 0 {
         0
     } else {
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 536a4726c6d..d9819484a96 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -34,7 +34,22 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `Add<impl Foo>` is not implemented for `u32`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error[E0283]: type annotations needed
+  --> $DIR/equality.rs:20:22
+   |
+LL | fn sum_to(n: u32) -> impl Foo {
+   |                      ^^^^^^^^ cannot infer type for type `{integer}`
+   |
+   = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate:
+           - impl ToString for i8;
+           - impl ToString for u8;
+note: required because of the requirements on the impl of `Foo` for `{integer}`
+  --> $DIR/equality.rs:5:26
+   |
+LL | impl<T: Copy + ToString> Foo for T {}
+   |                          ^^^     ^
 
-Some errors have detailed explanations: E0277, E0308.
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0277, E0283, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr
index 17fad571385..739847c5cd5 100644
--- a/src/test/ui/inference/issue-71732.stderr
+++ b/src/test/ui/inference/issue-71732.stderr
@@ -6,7 +6,10 @@ LL |         .get(&"key".into())
    |          |
    |          cannot infer type for type parameter `Q` declared on the associated function `get`
    |
-   = note: cannot satisfy `String: Borrow<_>`
+   = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
+           - impl Borrow<str> for String;
+           - impl<T> Borrow<T> for T
+             where T: ?Sized;
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr
index 3c9d864c426..0077c734748 100644
--- a/src/test/ui/inference/issue-72616.stderr
+++ b/src/test/ui/inference/issue-72616.stderr
@@ -6,7 +6,11 @@ LL |         if String::from("a") == "a".try_into().unwrap() {}
    |                              |
    |                              cannot infer type
    |
-   = note: cannot satisfy `String: PartialEq<_>`
+   = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate:
+           - impl PartialEq for String;
+           - impl<'a, 'b> PartialEq<&'a str> for String;
+           - impl<'a, 'b> PartialEq<Cow<'a, str>> for String;
+           - impl<'a, 'b> PartialEq<str> for String;
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr
index f00d5d32bbf..3b011f58b25 100644
--- a/src/test/ui/issues/issue-29147.stderr
+++ b/src/test/ui/issues/issue-29147.stderr
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed
 LL |     let _ = <S5<_>>::xxx;
    |             ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
    |
-   = note: cannot satisfy `S5<_>: Foo`
+note: multiple `impl`s satisfying `S5<_>: Foo` found
+  --> $DIR/issue-29147.rs:17:1
+   |
+LL | impl Foo for S5<u32> { fn xxx(&self) {} }
+   | ^^^^^^^^^^^^^^^^^^^^
+LL | impl Foo for S5<u64> { fn xxx(&self) {} }
+   | ^^^^^^^^^^^^^^^^^^^^
 note: required by `Foo::xxx`
   --> $DIR/issue-29147.rs:10:13
    |
diff --git a/src/test/ui/issues/issue-69455.rs b/src/test/ui/issues/issue-69455.rs
index f1935ae2534..a53aadcfad0 100644
--- a/src/test/ui/issues/issue-69455.rs
+++ b/src/test/ui/issues/issue-69455.rs
@@ -27,4 +27,5 @@ impl Test<u64> for u64 {
 fn main() {
     let xs: Vec<u64> = vec![1, 2, 3];
     println!("{}", 23u64.test(xs.iter().sum())); //~ ERROR: type annotations needed
+    //~^ ERROR type annotations needed
 }
diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr
index 430bbcabf83..da84a6b52da 100644
--- a/src/test/ui/issues/issue-69455.stderr
+++ b/src/test/ui/issues/issue-69455.stderr
@@ -4,6 +4,26 @@ error[E0284]: type annotations needed: cannot satisfy `<u64 as Test<_>>::Output
 LL |     println!("{}", 23u64.test(xs.iter().sum()));
    |                          ^^^^ cannot satisfy `<u64 as Test<_>>::Output == _`
 
-error: aborting due to previous error
+error[E0283]: type annotations needed
+  --> $DIR/issue-69455.rs:29:26
+   |
+LL |     println!("{}", 23u64.test(xs.iter().sum()));
+   |                          ^^^^ cannot infer type for type parameter `Rhs` declared on the trait `Test`
+   |
+note: multiple `impl`s satisfying `u64: Test<_>` found
+  --> $DIR/issue-69455.rs:11:1
+   |
+LL | impl Test<u32> for u64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Test<u64> for u64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying the type argument in the method call
+   |
+LL |     println!("{}", 23u64.test(xs.iter().sum::<S>()));
+   |                                            +++++
 
-For more information about this error, try `rustc --explain E0284`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0283, E0284.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/src/test/ui/issues/issue-69683.rs b/src/test/ui/issues/issue-69683.rs
index cc7f1fa0f55..7a76e9ef205 100644
--- a/src/test/ui/issues/issue-69683.rs
+++ b/src/test/ui/issues/issue-69683.rs
@@ -28,5 +28,6 @@ fn main() {
     let b: [u8; 3] = [0u8; 3];
 
     0u16.foo(b); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
     //<u16 as Foo<[(); 3]>>::foo(0u16, b);
 }
diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr
index 776370331a4..ecf78e48e0e 100644
--- a/src/test/ui/issues/issue-69683.stderr
+++ b/src/test/ui/issues/issue-69683.stderr
@@ -4,6 +4,22 @@ error[E0284]: type annotations needed: cannot satisfy `<u8 as Element<_>>::Array
 LL |     0u16.foo(b);
    |          ^^^ cannot satisfy `<u8 as Element<_>>::Array == [u8; 3]`
 
-error: aborting due to previous error
+error[E0283]: type annotations needed
+  --> $DIR/issue-69683.rs:30:10
+   |
+LL |     0u16.foo(b);
+   |          ^^^ cannot infer type for type parameter `I` declared on the trait `Foo`
+   |
+note: multiple `impl`s satisfying `u8: Element<_>` found
+  --> $DIR/issue-69683.rs:5:1
+   |
+LL | impl<T> Element<()> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl<T: Element<S>, S> Element<[S; 3]> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-For more information about this error, try `rustc --explain E0284`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0283, E0284.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs
index 4edbd9ca15d..916a7832c68 100644
--- a/src/test/ui/issues/issue-72690.rs
+++ b/src/test/ui/issues/issue-72690.rs
@@ -5,10 +5,13 @@ fn no_err() {
 
 fn err() {
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
 }
 
 fn arg_pat_closure_err() {
     |x| String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 fn local_pat_closure_err() {
@@ -17,12 +20,14 @@ fn local_pat_closure_err() {
 
 fn err_first_arg_pat() {
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
     |x: String| x;
 }
 
 fn err_second_arg_pat() {
     |x: String| x;
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
 }
 
 fn err_mid_arg_pat() {
@@ -31,6 +36,7 @@ fn err_mid_arg_pat() {
     |x: String| x;
     |x: String| x;
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
     |x: String| x;
     |x: String| x;
     |x: String| x;
@@ -39,12 +45,14 @@ fn err_mid_arg_pat() {
 
 fn err_first_local_pat() {
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
     let _ = String::from("x");
 }
 
 fn err_second_local_pat() {
     let _ = String::from("x");
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
 }
 
 fn err_mid_local_pat() {
@@ -53,6 +61,7 @@ fn err_mid_local_pat() {
     let _ = String::from("x");
     let _ = String::from("x");
     String::from("x".as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
     let _ = String::from("x");
     let _ = String::from("x");
     let _ = String::from("x");
diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr
index af3459a7d2d..1747ca5bb04 100644
--- a/src/test/ui/issues/issue-72690.stderr
+++ b/src/test/ui/issues/issue-72690.stderr
@@ -4,36 +4,89 @@ error[E0283]: type annotations needed
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
 LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:7:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
 error[E0282]: type annotations needed
-  --> $DIR/issue-72690.rs:11:6
+  --> $DIR/issue-72690.rs:12:6
    |
 LL |     |x| String::from("x".as_ref());
    |      ^ consider giving this closure parameter a type
 
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:12:9
+   |
+LL |     |x| String::from("x".as_ref());
+   |         ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:12:26
+   |
+LL |     |x| String::from("x".as_ref());
+   |                      ----^^^^^^--
+   |                      |   |
+   |                      |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                      this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
 error[E0283]: type annotations needed for `&T`
-  --> $DIR/issue-72690.rs:15:17
+  --> $DIR/issue-72690.rs:18:17
    |
 LL |     let _ = "x".as_ref();
    |         -       ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef`
    |         |
    |         consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified
    |
-   = note: cannot satisfy `str: AsRef<_>`
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:19:5
+  --> $DIR/issue-72690.rs:22:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
@@ -41,12 +94,29 @@ LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:25:5
+  --> $DIR/issue-72690.rs:22:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:29:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
@@ -54,12 +124,29 @@ LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:33:5
+  --> $DIR/issue-72690.rs:29:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:38:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
@@ -67,17 +154,19 @@ LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:41:5
+  --> $DIR/issue-72690.rs:38:22
    |
 LL |     String::from("x".as_ref());
-   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
    |
-   = note: cannot satisfy `String: From<&_>`
-note: required by `from`
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn from(_: T) -> Self;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:47:5
@@ -85,7 +174,9 @@ error[E0283]: type annotations needed
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
@@ -93,19 +184,81 @@ LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:55:5
+  --> $DIR/issue-72690.rs:47:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:54:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
    |
-   = note: cannot satisfy `String: From<&_>`
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
 LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 9 previous errors
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:54:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:63:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
+   |
+   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
+           - impl<> From<&String> for String;
+           - impl<> From<&str> for String;
+note: required by `from`
+  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+   |
+LL |     fn from(_: T) -> Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:63:22
+   |
+LL |     String::from("x".as_ref());
+   |                  ----^^^^^^--
+   |                  |   |
+   |                  |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |                  this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
+           - impl AsRef<OsStr> for str;
+           - impl AsRef<Path> for str;
+           - impl AsRef<[u8]> for str;
+           - impl AsRef<str> for str;
+
+error: aborting due to 18 previous errors
 
 Some errors have detailed explanations: E0282, E0283.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/marker_trait_attr/region-overlap.stderr b/src/test/ui/marker_trait_attr/region-overlap.stderr
index e4a94d56f12..c1cc6cdaf53 100644
--- a/src/test/ui/marker_trait_attr/region-overlap.stderr
+++ b/src/test/ui/marker_trait_attr/region-overlap.stderr
@@ -4,7 +4,13 @@ error[E0283]: type annotations needed
 LL | impl<'a> A for (&'static (), &'a ()) {}
    |          ^ cannot infer type for tuple `(&'static (), &'a ())`
    |
-   = note: cannot satisfy `(&'static (), &'a ()): A`
+note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found
+  --> $DIR/region-overlap.rs:5:1
+   |
+LL | impl<'a> A for (&'static (), &'a ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> A for (&'a (), &'static ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `A`
   --> $DIR/region-overlap.rs:4:1
    |
@@ -17,7 +23,13 @@ error[E0283]: type annotations needed
 LL | impl<'a> A for (&'a (), &'static ()) {}
    |          ^ cannot infer type for tuple `(&'a (), &'static ())`
    |
-   = note: cannot satisfy `(&'a (), &'static ()): A`
+note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found
+  --> $DIR/region-overlap.rs:5:1
+   |
+LL | impl<'a> A for (&'static (), &'a ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> A for (&'a (), &'static ()) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `A`
   --> $DIR/region-overlap.rs:4:1
    |
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
index 49fe7d1324c..7b2fc34e1af 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs
@@ -23,7 +23,7 @@ fn m1() {
     // we couldn't infer the type of the vector just based on calling foo()...
     let mut x = Vec::new();
     //~^ ERROR type annotations needed
-    x.foo();
+    x.foo(); //~ ERROR type annotations needed
 }
 
 fn m2() {
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index 4b494c96115..f33672433de 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -6,6 +6,21 @@ LL |     let mut x = Vec::new();
    |         |
    |         consider giving `x` the explicit type `Vec<T>`, where the type parameter `T` is specified
 
+error[E0283]: type annotations needed
+  --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7
+   |
+LL |     x.foo();
+   |       ^^^ cannot infer type for struct `Vec<_>`
+   |
+note: multiple `impl`s satisfying `Vec<_>: Foo` found
+  --> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1
+   |
+LL | impl Foo for Vec<usize> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Foo for Vec<isize> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0308]: mismatched types
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20
    |
@@ -19,7 +34,7 @@ help: you can convert an `isize` to a `usize` and panic if the converted value d
 LL |     let y: usize = x.foo().try_into().unwrap();
    |                           ++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0282, E0308.
+Some errors have detailed explanations: E0282, E0283, E0308.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/traits/issue-77982.rs b/src/test/ui/traits/issue-77982.rs
index 03d4fe23cc5..f5be6cf21c1 100644
--- a/src/test/ui/traits/issue-77982.rs
+++ b/src/test/ui/traits/issue-77982.rs
@@ -6,6 +6,7 @@ fn what() {
     let opt = String::new();
 
     opts.get(opt.as_ref()); //~ ERROR type annotations needed
+    //~^ ERROR type annotations needed
 }
 
 fn main() {
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index 68347207bda..c45bd76524f 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -6,17 +6,50 @@ LL |     opts.get(opt.as_ref());
    |          |
    |          cannot infer type for type parameter `Q` declared on the associated function `get`
    |
-   = note: cannot satisfy `String: Borrow<_>`
+   = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
+           - impl Borrow<str> for String;
+           - impl<T> Borrow<T> for T
+             where T: ?Sized;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-77982.rs:12:44
+  --> $DIR/issue-77982.rs:8:18
+   |
+LL |     opts.get(opt.as_ref());
+   |              ----^^^^^^--
+   |              |   |
+   |              |   cannot infer type for type parameter `T` declared on the trait `AsRef`
+   |              this method call resolves to `&T`
+   |
+   = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`:
+           - impl AsRef<OsStr> for String;
+           - impl AsRef<Path> for String;
+           - impl AsRef<[u8]> for String;
+           - impl AsRef<str> for String;
+help: use the fully qualified path for the potential candidates
+   |
+LL |     opts.get(<String as AsRef<OsStr>>::as_ref(opt));
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     opts.get(<String as AsRef<Path>>::as_ref(opt));
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     opts.get(<String as AsRef<str>>::as_ref(opt));
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     opts.get(<String as AsRef<[u8]>>::as_ref(opt));
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-77982.rs:13:44
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
    |                                            ^^^^^^^^^ ----------- this method call resolves to `T`
    |                                            |
    |                                            cannot infer type for type parameter `T` declared on the trait `From`
    |
-   = note: cannot satisfy `u32: From<_>`
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+           - impl From<Ipv4Addr> for u32;
+           - impl From<NonZeroU32> for u32;
+           - impl From<bool> for u32;
+           - impl From<char> for u32;
+           and 3 more
 note: required by `from`
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
@@ -24,25 +57,37 @@ LL |     fn from(_: T) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed for `Box<T>`
-  --> $DIR/issue-77982.rs:35:16
+  --> $DIR/issue-77982.rs:36:16
    |
 LL |     let _ = ().foo();
    |         -      ^^^ cannot infer type for type parameter `T` declared on the trait `Foo`
    |         |
    |         consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified
    |
-   = note: cannot satisfy `(): Foo<'_, _>`
+note: multiple `impl`s satisfying `(): Foo<'_, _>` found
+  --> $DIR/issue-77982.rs:29:1
+   |
+LL | impl Foo<'static, u32> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> Foo<'a, i16> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0283]: type annotations needed for `Box<T>`
-  --> $DIR/issue-77982.rs:39:19
+  --> $DIR/issue-77982.rs:40:19
    |
 LL |     let _ = (&()).bar();
    |         -         ^^^ cannot infer type for type parameter `T` declared on the trait `Bar`
    |         |
    |         consider giving this pattern the explicit type `Box<T>`, where the type parameter `T` is specified
    |
-   = note: cannot satisfy `&(): Bar<'_, _>`
+note: multiple `impl`s satisfying `&(): Bar<'_, _>` found
+  --> $DIR/issue-77982.rs:32:1
+   |
+LL | impl<'a> Bar<'static, u32> for &'a () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<'a> Bar<'a, i16> for &'a () {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.rs b/src/test/ui/traits/multidispatch-convert-ambig-dest.rs
index 58cb69a05b7..aa74e11c362 100644
--- a/src/test/ui/traits/multidispatch-convert-ambig-dest.rs
+++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.rs
@@ -24,7 +24,8 @@ where T : Convert<U>
 
 fn a() {
     test(22, std::default::Default::default());
-    //~^ ERROR type annotations needed [E0282]
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
index 62f5f5aaa88..9fd81b56bf1 100644
--- a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
+++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
@@ -4,6 +4,33 @@ error[E0282]: type annotations needed
 LL |     test(22, std::default::Default::default());
    |     ^^^^ cannot infer type for type parameter `U` declared on the function `test`
 
-error: aborting due to previous error
+error[E0283]: type annotations needed
+  --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
+   |
+LL |     test(22, std::default::Default::default());
+   |     ^^^^ cannot infer type for type parameter `U` declared on the function `test`
+   |
+note: multiple `impl`s satisfying `i32: Convert<_>` found
+  --> $DIR/multidispatch-convert-ambig-dest.rs:8:1
+   |
+LL | impl Convert<i8> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Convert<i16> for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `test`
+  --> $DIR/multidispatch-convert-ambig-dest.rs:21:11
+   |
+LL | fn test<T,U>(_: T, _: U)
+   |    ---- required by a bound in this
+LL | where T : Convert<U>
+   |           ^^^^^^^^^^ required by this bound in `test`
+help: consider specifying the type arguments in the function call
+   |
+LL |     test::<T, U>(22, std::default::Default::default());
+   |         ++++++++
 
-For more information about this error, try `rustc --explain E0282`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs
index 342928e882a..d062de25ac8 100644
--- a/src/test/ui/traits/test-2.rs
+++ b/src/test/ui/traits/test-2.rs
@@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>();
+    10.dup::<i32>(); //~ ERROR type annotations needed
     //~^ ERROR this associated function takes 0 generic arguments but 1
-    10.blah::<i32, i32>();
+    10.blah::<i32, i32>(); //~ ERROR type annotations needed
     //~^ ERROR this associated function takes 1 generic argument but 2
     (Box::new(10) as Box<dyn bar>).dup();
     //~^ ERROR E0038
diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr
index 77ea4e4e974..5eec0124584 100644
--- a/src/test/ui/traits/test-2.stderr
+++ b/src/test/ui/traits/test-2.stderr
@@ -79,7 +79,35 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
    = note: required by cast to type `Box<dyn bar>`
 
-error: aborting due to 5 previous errors
+error[E0283]: type annotations needed
+  --> $DIR/test-2.rs:9:8
+   |
+LL |     10.dup::<i32>();
+   |        ^^^ cannot infer type for type `{integer}`
+   |
+note: multiple `impl`s satisfying `{integer}: bar` found
+  --> $DIR/test-2.rs:5:1
+   |
+LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
+   | ^^^^^^^^^^^^^^^^
+LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
+   | ^^^^^^^^^^^^^^^^
 
-Some errors have detailed explanations: E0038, E0107.
+error[E0283]: type annotations needed
+  --> $DIR/test-2.rs:11:8
+   |
+LL |     10.blah::<i32, i32>();
+   |        ^^^^ cannot infer type for type `{integer}`
+   |
+note: multiple `impl`s satisfying `{integer}: bar` found
+  --> $DIR/test-2.rs:5:1
+   |
+LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
+   | ^^^^^^^^^^^^^^^^
+LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0038, E0107, E0283.
 For more information about an error, try `rustc --explain E0038`.

From 881a50c0b7c089831aaf403e9238f77deefe04c3 Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Fri, 1 Oct 2021 18:09:31 +0000
Subject: [PATCH 2/2] Always sort suggestions before emitting them

---
 compiler/rustc_errors/src/diagnostic.rs       | 10 +++++++---
 .../ui/deprecation/invalid-literal.stderr     |  8 ++++----
 src/test/ui/did_you_mean/issue-42764.stderr   |  4 ++--
 .../issue-43106-gating-of-macro_use.stderr    |  4 ++--
 .../no-method-suggested-traits.stderr         |  8 ++++----
 src/test/ui/issues/issue-73427.stderr         |  8 ++++----
 .../ui/on-unimplemented/bad-annotation.stderr |  4 ++--
 .../core-std-import-order-issue-83564.stderr  |  4 ++--
 src/test/ui/traits/issue-77982.stderr         |  4 ++--
 .../clippy/tests/ui/nonminimal_bool.stderr    | 20 +++++++++----------
 10 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 41a73268f46..f2381d75c56 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -465,10 +465,14 @@ impl Diagnostic {
         suggestions: impl Iterator<Item = String>,
         applicability: Applicability,
     ) -> &mut Self {
+        let mut suggestions: Vec<_> = suggestions.collect();
+        suggestions.sort();
+        let substitutions = suggestions
+            .into_iter()
+            .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
+            .collect();
         self.suggestions.push(CodeSuggestion {
-            substitutions: suggestions
-                .map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
-                .collect(),
+            substitutions,
             msg: msg.to_owned(),
             style: SuggestionStyle::ShowCode,
             applicability,
diff --git a/src/test/ui/deprecation/invalid-literal.stderr b/src/test/ui/deprecation/invalid-literal.stderr
index f15be95db10..b56eedeb80d 100644
--- a/src/test/ui/deprecation/invalid-literal.stderr
+++ b/src/test/ui/deprecation/invalid-literal.stderr
@@ -6,12 +6,12 @@ LL | #[deprecated = b"test"]
    |
 help: the following are the possible correct uses
    |
-LL | #[deprecated]
-   | ~~~~~~~~~~~~~
-LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")]
-   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL | #[deprecated = "reason"]
    | ~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")]
+   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | #[deprecated]
+   | ~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr
index b339ce5ce8c..bc8a93757a5 100644
--- a/src/test/ui/did_you_mean/issue-42764.stderr
+++ b/src/test/ui/did_you_mean/issue-42764.stderr
@@ -8,10 +8,10 @@ LL |     this_function_expects_a_double_option(n);
               found type `usize`
 help: try using a variant of the expected enum
    |
-LL |     this_function_expects_a_double_option(DoubleOption::FirstSome(n));
-   |                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     this_function_expects_a_double_option(DoubleOption::AlternativeSome(n));
    |                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     this_function_expects_a_double_option(DoubleOption::FirstSome(n));
+   |                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-42764.rs:27:33
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
index c0d2df3753d..9a12851f20e 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
@@ -24,10 +24,10 @@ LL |     #[macro_use = "2700"] struct S;
    |
 help: the following are the possible correct uses
    |
-LL |     #[macro_use] struct S;
-   |     ~~~~~~~~~~~~
 LL |     #[macro_use(name1, name2, ...)] struct S;
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     #[macro_use] struct S;
+   |     ~~~~~~~~~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index 30afc8646de..c8ebed3bfd9 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -9,12 +9,12 @@ help: the following traits are implemented but not in scope; perhaps add a `use`
    |
 LL | use foo::Bar;
    |
+LL | use no_method_suggested_traits::Reexported;
+   |
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 LL | use no_method_suggested_traits::qux::PrivPub;
    |
-LL | use no_method_suggested_traits::Reexported;
-   |
 
 error[E0599]: no method named `method` found for struct `Rc<&mut Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:26:44
@@ -27,12 +27,12 @@ help: the following traits are implemented but not in scope; perhaps add a `use`
    |
 LL | use foo::Bar;
    |
+LL | use no_method_suggested_traits::Reexported;
+   |
 LL | use no_method_suggested_traits::foo::PubPub;
    |
 LL | use no_method_suggested_traits::qux::PrivPub;
    |
-LL | use no_method_suggested_traits::Reexported;
-   |
 
 error[E0599]: no method named `method` found for type `char` in the current scope
   --> $DIR/no-method-suggested-traits.rs:30:9
diff --git a/src/test/ui/issues/issue-73427.stderr b/src/test/ui/issues/issue-73427.stderr
index 54df7fccaa5..59bb98a340a 100644
--- a/src/test/ui/issues/issue-73427.stderr
+++ b/src/test/ui/issues/issue-73427.stderr
@@ -120,10 +120,10 @@ LL | | }
    | |_^
 help: try to construct one of the enum's variants
    |
-LL |     let x = A::TupleWithFields(3);
-   |             ~~~~~~~~~~~~~~~~~~
 LL |     let x = A::Tuple(3);
    |             ~~~~~~~~
+LL |     let x = A::TupleWithFields(3);
+   |             ~~~~~~~~~~~~~~~~~~
 
 error[E0532]: expected tuple struct or tuple variant, found enum `A`
   --> $DIR/issue-73427.rs:42:12
@@ -145,10 +145,10 @@ LL | | }
    | |_^
 help: try to match against one of the enum's variants
    |
-LL |     if let A::TupleWithFields(3) = x { }
-   |            ~~~~~~~~~~~~~~~~~~
 LL |     if let A::Tuple(3) = x { }
    |            ~~~~~~~~
+LL |     if let A::TupleWithFields(3) = x { }
+   |            ~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr
index ac0cf0f1f08..a8d3c8680fa 100644
--- a/src/test/ui/on-unimplemented/bad-annotation.stderr
+++ b/src/test/ui/on-unimplemented/bad-annotation.stderr
@@ -6,10 +6,10 @@ LL | #[rustc_on_unimplemented]
    |
 help: the following are the possible correct uses
    |
-LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]
-   |
 LL | #[rustc_on_unimplemented = "message"]
    |
+LL | #[rustc_on_unimplemented(/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...")]
+   |
 
 error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
   --> $DIR/bad-annotation.rs:22:1
diff --git a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr
index d484fb8cbe0..ce85d93b96c 100644
--- a/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr
+++ b/src/test/ui/suggestions/core-std-import-order-issue-83564.stderr
@@ -6,10 +6,10 @@ LL |     let _x = NonZeroU32::new(5).unwrap();
    |
 help: consider importing one of these items
    |
-LL | use std::num::NonZeroU32;
-   |
 LL | use core::num::NonZeroU32;
    |
+LL | use std::num::NonZeroU32;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index c45bd76524f..e868756504f 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -31,10 +31,10 @@ LL |     opts.get(<String as AsRef<OsStr>>::as_ref(opt));
    |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     opts.get(<String as AsRef<Path>>::as_ref(opt));
    |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL |     opts.get(<String as AsRef<str>>::as_ref(opt));
-   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 LL |     opts.get(<String as AsRef<[u8]>>::as_ref(opt));
    |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     opts.get(<String as AsRef<str>>::as_ref(opt));
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0283]: type annotations needed
   --> $DIR/issue-77982.rs:13:44
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index 1d39bce935d..bb93cbbd5e1 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -50,10 +50,10 @@ LL |     let _ = a == b && c == 5 && a == b;
    |
 help: try
    |
-LL |     let _ = a == b && c == 5;
-   |             ~~~~~~~~~~~~~~~~
 LL |     let _ = !(a != b || c != 5);
    |             ~~~~~~~~~~~~~~~~~~~
+LL |     let _ = a == b && c == 5;
+   |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
   --> $DIR/nonminimal_bool.rs:28:13
@@ -63,10 +63,10 @@ LL |     let _ = a == b || c == 5 || a == b;
    |
 help: try
    |
-LL |     let _ = a == b || c == 5;
-   |             ~~~~~~~~~~~~~~~~
 LL |     let _ = !(a != b && c != 5);
    |             ~~~~~~~~~~~~~~~~~~~
+LL |     let _ = a == b || c == 5;
+   |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
   --> $DIR/nonminimal_bool.rs:29:13
@@ -76,10 +76,10 @@ LL |     let _ = a == b && c == 5 && b == a;
    |
 help: try
    |
-LL |     let _ = a == b && c == 5;
-   |             ~~~~~~~~~~~~~~~~
 LL |     let _ = !(a != b || c != 5);
    |             ~~~~~~~~~~~~~~~~~~~
+LL |     let _ = a == b && c == 5;
+   |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
   --> $DIR/nonminimal_bool.rs:30:13
@@ -89,10 +89,10 @@ LL |     let _ = a != b || !(a != b || c == d);
    |
 help: try
    |
-LL |     let _ = a != b || c != d;
-   |             ~~~~~~~~~~~~~~~~
 LL |     let _ = !(a == b && c == d);
    |             ~~~~~~~~~~~~~~~~~~~
+LL |     let _ = a != b || c != d;
+   |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
   --> $DIR/nonminimal_bool.rs:31:13
@@ -102,10 +102,10 @@ LL |     let _ = a != b && !(a != b && c == d);
    |
 help: try
    |
-LL |     let _ = a != b && c != d;
-   |             ~~~~~~~~~~~~~~~~
 LL |     let _ = !(a == b || c == d);
    |             ~~~~~~~~~~~~~~~~~~~
+LL |     let _ = a != b && c != d;
+   |             ~~~~~~~~~~~~~~~~
 
 error: aborting due to 12 previous errors