]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/stable_sort_primitive.rs
Auto merge of #8937 - Jarcho:merge_match_passes, r=llogiq
[rust.git] / clippy_lints / src / stable_sort_primitive.rs
index cd7056620a2e02c19744a17b42e0b129bb9bbc8a..a6c685df721d6fac310117306cb98cd2b46f9a96 100644 (file)
@@ -1,29 +1,34 @@
-use crate::utils::{is_slice_of_primitives, span_lint_and_sugg, sugg::Sugg};
-
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{is_slice_of_primitives, sugg::Sugg};
 use if_chain::if_chain;
-
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
-    /// **What it does:**
+    /// ### What it does
     /// When sorting primitive values (integers, bools, chars, as well
-    /// as arrays, slices, and tuples of such items), it is better to
+    /// as arrays, slices, and tuples of such items), it is typically better to
     /// use an unstable sort than a stable sort.
     ///
-    /// **Why is this bad?**
-    /// Using a stable sort consumes more memory and cpu cycles. Because
-    /// values which compare equal are identical, preserving their
+    /// ### Why is this bad?
+    /// Typically, using a stable sort consumes more memory and cpu cycles.
+    /// Because values which compare equal are identical, preserving their
     /// relative order (the guarantee that a stable sort provides) means
     /// nothing, while the extra costs still apply.
     ///
-    /// **Known problems:**
-    /// None
+    /// ### Known problems
     ///
-    /// **Example:**
+    /// As pointed out in
+    /// [issue #8241](https://github.com/rust-lang/rust-clippy/issues/8241),
+    /// a stable sort can instead be significantly faster for certain scenarios
+    /// (eg. when a sorted vector is extended with new data and resorted).
     ///
+    /// For more information and benchmarking results, please refer to the
+    /// issue linked above.
+    ///
+    /// ### Example
     /// ```rust
     /// let mut vec = vec![2, 1, 3];
     /// vec.sort();
@@ -33,8 +38,9 @@
     /// let mut vec = vec![2, 1, 3];
     /// vec.sort_unstable();
     /// ```
+    #[clippy::version = "1.47.0"]
     pub STABLE_SORT_PRIMITIVE,
-    perf,
+    pedantic,
     "use of sort() when sort_unstable() is equivalent"
 }
 
@@ -86,17 +92,18 @@ struct LintDetection {
     slice_name: String,
     method: SortingKind,
     method_args: String,
+    slice_type: String,
 }
 
 fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintDetection> {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(method_name, args, _) = &expr.kind;
         if let Some(slice) = &args.get(0);
-        if let Some(method) = SortingKind::from_stable_name(&method_name.ident.name.as_str());
-        if is_slice_of_primitives(cx, slice);
+        if let Some(method) = SortingKind::from_stable_name(method_name.ident.name.as_str());
+        if let Some(slice_type) = is_slice_of_primitives(cx, slice);
         then {
             let args_str = args.iter().skip(1).map(|arg| Sugg::hir(cx, arg, "..").to_string()).collect::<Vec<String>>().join(", ");
-            Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str })
+            Some(LintDetection { slice_name: Sugg::hir(cx, slice, "..").to_string(), method, method_args: args_str, slice_type })
         } else {
             None
         }
@@ -106,24 +113,32 @@ fn detect_stable_sort_primitive(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option
 impl LateLintPass<'_> for StableSortPrimitive {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if let Some(detection) = detect_stable_sort_primitive(cx, expr) {
-            span_lint_and_sugg(
+            span_lint_and_then(
                 cx,
                 STABLE_SORT_PRIMITIVE,
                 expr.span,
                 format!(
-                    "Use {} instead of {}",
-                    detection.method.unstable_name(),
-                    detection.method.stable_name()
+                    "used `{}` on primitive type `{}`",
+                    detection.method.stable_name(),
+                    detection.slice_type,
                 )
                 .as_str(),
-                "try",
-                format!(
-                    "{}.{}({})",
-                    detection.slice_name,
-                    detection.method.unstable_name(),
-                    detection.method_args
-                ),
-                Applicability::MachineApplicable,
+                |diag| {
+                    diag.span_suggestion(
+                        expr.span,
+                        "try",
+                        format!(
+                            "{}.{}({})",
+                            detection.slice_name,
+                            detection.method.unstable_name(),
+                            detection.method_args,
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                    diag.note(
+                        "an unstable sort typically performs faster without any observable difference for this data type",
+                    );
+                },
             );
         }
     }