about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-17 19:43:39 +0000
committerbors <bors@rust-lang.org>2023-04-17 19:43:39 +0000
commit203c909d04ffc0b2c22f97cb304649aac237087e (patch)
treef1c2ca0d6bd832033db66a4fbc3dcdebc449f9a0
parente57deaace54648bf4e35bf121f23f92df4e6e0c6 (diff)
parenta2580db6420aa6ea3ab34c467bb795e9e39ba449 (diff)
downloadrust-203c909d04ffc0b2c22f97cb304649aac237087e.tar.gz
rust-203c909d04ffc0b2c22f97cb304649aac237087e.zip
Auto merge of #10661 - timvisee:manual-slice-size-calc-suggestion, r=Manishearth
Add `manual_slice_size_calculation` applicable suggestion

Continuation of https://github.com/rust-lang/rust-clippy/pull/10659#issuecomment-1511688869.

This adds applicable suggestions to the `manual_slice_size_calculation` lint:

```
error: manual slice size calculation
  --> $DIR/manual_slice_size_calculation.rs:11:13
   |
LL |     let _ = s_i32.len() * size_of::<i32>(); // WARNING
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
   |
   = note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings`
```

changelog: [`manual_slice_size_calculation`]: add machine applicable suggestion
-rw-r--r--clippy_lints/src/manual_slice_size_calculation.rs26
-rw-r--r--tests/ui/manual_slice_size_calculation.fixed37
-rw-r--r--tests/ui/manual_slice_size_calculation.rs1
-rw-r--r--tests/ui/manual_slice_size_calculation.stderr35
4 files changed, 68 insertions, 31 deletions
diff --git a/clippy_lints/src/manual_slice_size_calculation.rs b/clippy_lints/src/manual_slice_size_calculation.rs
index ba01fd08530..a5bb1c6f9bc 100644
--- a/clippy_lints/src/manual_slice_size_calculation.rs
+++ b/clippy_lints/src/manual_slice_size_calculation.rs
@@ -1,5 +1,8 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{expr_or_init, in_constant};
+// run-rustfix
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::{expr_or_init, in_constant, std_or_core};
+use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
@@ -42,15 +45,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation {
         if !in_constant(cx, expr.hir_id)
             && let ExprKind::Binary(ref op, left, right) = expr.kind
             && BinOpKind::Mul == op.node
-            && let Some(_receiver) = simplify(cx, left, right)
+            && let Some(receiver) = simplify(cx, left, right)
         {
-            span_lint_and_help(
+            let ctxt = expr.span.ctxt();
+            let mut app = Applicability::MachineApplicable;
+            let val_name = snippet_with_context(cx, receiver.span, ctxt, "slice", &mut app).0;
+            let Some(sugg) = std_or_core(cx) else { return };
+
+            span_lint_and_sugg(
                 cx,
                 MANUAL_SLICE_SIZE_CALCULATION,
-                expr.span,
-                "manual slice size calculation",
-                None,
-                "consider using std::mem::size_of_val instead");
+                    expr.span,
+                    "manual slice size calculation",
+                    "try",
+                    format!("{sugg}::mem::size_of_val({val_name})"),
+                    Applicability::MachineApplicable,
+                );
         }
     }
 }
diff --git a/tests/ui/manual_slice_size_calculation.fixed b/tests/ui/manual_slice_size_calculation.fixed
new file mode 100644
index 00000000000..2b18dd58c63
--- /dev/null
+++ b/tests/ui/manual_slice_size_calculation.fixed
@@ -0,0 +1,37 @@
+// run-rustfix
+#![allow(unused)]
+#![warn(clippy::manual_slice_size_calculation)]
+
+use core::mem::{align_of, size_of};
+
+fn main() {
+    let v_i32 = Vec::<i32>::new();
+    let s_i32 = v_i32.as_slice();
+
+    // True positives:
+    let _ = std::mem::size_of_val(s_i32); // WARNING
+    let _ = std::mem::size_of_val(s_i32); // WARNING
+    let _ = std::mem::size_of_val(s_i32) * 5; // WARNING
+
+    let len = s_i32.len();
+    let size = size_of::<i32>();
+    let _ = std::mem::size_of_val(s_i32); // WARNING
+    let _ = std::mem::size_of_val(s_i32); // WARNING
+    let _ = std::mem::size_of_val(s_i32); // WARNING
+
+    // True negatives:
+    let _ = size_of::<i32>() + s_i32.len(); // Ok, not a multiplication
+    let _ = size_of::<i32>() * s_i32.partition_point(|_| true); // Ok, not len()
+    let _ = size_of::<i32>() * v_i32.len(); // Ok, not a slice
+    let _ = align_of::<i32>() * s_i32.len(); // Ok, not size_of()
+    let _ = size_of::<u32>() * s_i32.len(); // Ok, different types
+
+    // False negatives:
+    let _ = 5 * size_of::<i32>() * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+    let _ = size_of::<i32>() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+}
+
+const fn _const(s_i32: &[i32]) {
+    // True negative:
+    let _ = s_i32.len() * size_of::<i32>(); // Ok, can't use size_of_val in const
+}
diff --git a/tests/ui/manual_slice_size_calculation.rs b/tests/ui/manual_slice_size_calculation.rs
index 5082f931f3c..04adab76df2 100644
--- a/tests/ui/manual_slice_size_calculation.rs
+++ b/tests/ui/manual_slice_size_calculation.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 #![allow(unused)]
 #![warn(clippy::manual_slice_size_calculation)]
 
diff --git a/tests/ui/manual_slice_size_calculation.stderr b/tests/ui/manual_slice_size_calculation.stderr
index 7698d9782f0..a6217652b88 100644
--- a/tests/ui/manual_slice_size_calculation.stderr
+++ b/tests/ui/manual_slice_size_calculation.stderr
@@ -1,51 +1,40 @@
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:11:13
+  --> $DIR/manual_slice_size_calculation.rs:12:13
    |
 LL |     let _ = s_i32.len() * size_of::<i32>(); // WARNING
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
    |
-   = help: consider using std::mem::size_of_val instead
    = note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings`
 
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:12:13
+  --> $DIR/manual_slice_size_calculation.rs:13:13
    |
 LL |     let _ = size_of::<i32>() * s_i32.len(); // WARNING
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using std::mem::size_of_val instead
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
 
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:13:13
+  --> $DIR/manual_slice_size_calculation.rs:14:13
    |
 LL |     let _ = size_of::<i32>() * s_i32.len() * 5; // WARNING
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using std::mem::size_of_val instead
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
 
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:17:13
+  --> $DIR/manual_slice_size_calculation.rs:18:13
    |
 LL |     let _ = len * size_of::<i32>(); // WARNING
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using std::mem::size_of_val instead
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
 
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:18:13
+  --> $DIR/manual_slice_size_calculation.rs:19:13
    |
 LL |     let _ = s_i32.len() * size; // WARNING
-   |             ^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider using std::mem::size_of_val instead
+   |             ^^^^^^^^^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
 
 error: manual slice size calculation
-  --> $DIR/manual_slice_size_calculation.rs:19:13
+  --> $DIR/manual_slice_size_calculation.rs:20:13
    |
 LL |     let _ = len * size; // WARNING
-   |             ^^^^^^^^^^
-   |
-   = help: consider using std::mem::size_of_val instead
+   |             ^^^^^^^^^^ help: try: `std::mem::size_of_val(s_i32)`
 
 error: aborting due to 6 previous errors