about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2022-04-24 09:46:17 -0400
committerJason Newcomb <jsnewcomb@pm.me>2022-05-15 17:39:39 -0400
commitf1574cc1319cbf4cd915568f0dc165815de93caf (patch)
tree14bf41d562a16de5b2441f6f4c2d77dc5e7e2bdc
parent948af01633337b3ab57f0db84d49128c5dbc417b (diff)
downloadrust-f1574cc1319cbf4cd915568f0dc165815de93caf.tar.gz
rust-f1574cc1319cbf4cd915568f0dc165815de93caf.zip
Update `vec_init_then_push` docs
-rw-r--r--clippy_lints/src/vec_init_then_push.rs13
-rw-r--r--tests/ui/vec_init_then_push.rs20
-rw-r--r--tests/ui/vec_init_then_push.stderr18
3 files changed, 45 insertions, 6 deletions
diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs
index 5a5dfcfdc8a..35db45e2b0c 100644
--- a/clippy_lints/src/vec_init_then_push.rs
+++ b/clippy_lints/src/vec_init_then_push.rs
@@ -18,6 +18,13 @@ declare_clippy_lint! {
     /// ### What it does
     /// Checks for calls to `push` immediately after creating a new `Vec`.
     ///
+    /// If the `Vec` is created using `with_capacity` this will only lint if the capacity is a
+    /// constant and the number of pushes is greater than or equal to the initial capacity.
+    ///
+    /// If the `Vec` is extended after the initial sequence of pushes and it was default initialized
+    /// then this will only lint after there were at least four pushes. This number may change in
+    /// the future.
+    ///
     /// ### Why is this bad?
     /// The `vec![]` macro is both more performant and easier to read than
     /// multiple `push` calls.
@@ -56,7 +63,7 @@ struct VecPushSearcher {
 }
 impl VecPushSearcher {
     fn display_err(&self, cx: &LateContext<'_>) {
-        let min_pushes_for_extension = match self.init {
+        let required_pushes_before_extension = match self.init {
             _ if self.found == 0 => return,
             VecInitKind::WithConstCapacity(x) if x > self.found => return,
             VecInitKind::WithConstCapacity(x) => x,
@@ -98,6 +105,8 @@ impl VecPushSearcher {
                         && adjusted_mut == Mutability::Mut
                         && !adjusted_ty.peel_refs().is_slice() =>
                 {
+                    // No need to set `needs_mut` to true. The receiver will be either explicitly borrowed, or it will
+                    // be implicitly borrowed via an adjustment. Both of these cases are already handled by this point.
                     return ControlFlow::Break(true);
                 },
                 ExprKind::Assign(lhs, ..) if e.hir_id == lhs.hir_id => {
@@ -110,7 +119,7 @@ impl VecPushSearcher {
         });
 
         // Avoid allocating small `Vec`s when they'll be extended right after.
-        if res == ControlFlow::Break(true) && self.found <= min_pushes_for_extension {
+        if res == ControlFlow::Break(true) && self.found <= required_pushes_before_extension {
             return;
         }
 
diff --git a/tests/ui/vec_init_then_push.rs b/tests/ui/vec_init_then_push.rs
index 768ea3e668a..531745424a7 100644
--- a/tests/ui/vec_init_then_push.rs
+++ b/tests/ui/vec_init_then_push.rs
@@ -29,6 +29,12 @@ fn main() {
         // no lint
         vec.push(1);
     }
+
+    let mut vec = Vec::with_capacity(5);
+    vec.push(1);
+    vec.push(2);
+    vec.push(3);
+    vec.push(4);
 }
 
 pub fn no_lint() -> Vec<i32> {
@@ -84,5 +90,17 @@ fn _cond_push_with_large_start(x: bool) -> Vec<u32> {
     if x {
         v.push(1);
     }
-    v
+
+    let mut v2 = Vec::new();
+    v2.push(0);
+    v2.push(1);
+    v2.push(0);
+    v2.push(1);
+    v2.push(0);
+    v2.push(0);
+    v2.push(1);
+    v2.push(0);
+    v2.extend(&v);
+
+    v2
 }
diff --git a/tests/ui/vec_init_then_push.stderr b/tests/ui/vec_init_then_push.stderr
index 362c9603bbf..50b029fc337 100644
--- a/tests/ui/vec_init_then_push.stderr
+++ b/tests/ui/vec_init_then_push.stderr
@@ -31,7 +31,7 @@ LL | |     new_err.push(0);
    | |____________________^ help: consider using the `vec![]` macro: `new_err = vec![..];`
 
 error: calls to `push` immediately after creation
-  --> $DIR/vec_init_then_push.rs:67:5
+  --> $DIR/vec_init_then_push.rs:73:5
    |
 LL | /     let mut v = Vec::new();
 LL | |     v.push(x);
@@ -39,7 +39,7 @@ LL | |     v.push(1);
    | |______________^ help: consider using the `vec![]` macro: `let mut v = vec![..];`
 
 error: calls to `push` immediately after creation
-  --> $DIR/vec_init_then_push.rs:75:5
+  --> $DIR/vec_init_then_push.rs:81:5
    |
 LL | /     let mut v = Vec::new();
 LL | |     v.push(0);
@@ -50,5 +50,17 @@ LL | |     v.push(1);
 LL | |     v.push(0);
    | |______________^ help: consider using the `vec![]` macro: `let mut v = vec![..];`
 
-error: aborting due to 6 previous errors
+error: calls to `push` immediately after creation
+  --> $DIR/vec_init_then_push.rs:94:5
+   |
+LL | /     let mut v2 = Vec::new();
+LL | |     v2.push(0);
+LL | |     v2.push(1);
+LL | |     v2.push(0);
+...  |
+LL | |     v2.push(1);
+LL | |     v2.push(0);
+   | |_______________^ help: consider using the `vec![]` macro: `let mut v2 = vec![..];`
+
+error: aborting due to 7 previous errors