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] 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