about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillem Nieto <gnieto.talo@gmail.com>2018-10-26 22:35:16 +0200
committerGuillem Nieto <gnieto@scopely.com>2018-11-25 14:34:23 -0800
commit9b4bc3b6efcb9daf8c1daf9f7f2a8bfa19973ad8 (patch)
treeada71756d035c9e5a3c1b9243f24cca1cd49979e
parente0ccc9d9afa2b7800e288a6367422b2a2389f57e (diff)
downloadrust-9b4bc3b6efcb9daf8c1daf9f7f2a8bfa19973ad8.tar.gz
rust-9b4bc3b6efcb9daf8c1daf9f7f2a8bfa19973ad8.zip
Add unsafe set_len initialization
-rw-r--r--clippy_lints/src/slow_vector_initialization.rs40
-rw-r--r--tests/ui/slow_vector_initialization.rs9
-rw-r--r--tests/ui/slow_vector_initialization.stderr86
3 files changed, 92 insertions, 43 deletions
diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs
index 52855031a5a..5d0b302e06b 100644
--- a/clippy_lints/src/slow_vector_initialization.rs
+++ b/clippy_lints/src/slow_vector_initialization.rs
@@ -71,6 +71,9 @@ enum InitializationType<'tcx> {
 
     /// Resize is a slow initialization with the form `vec.resize(.., 0)`
     Resize(&'tcx Expr),
+
+    /// UnsafeSetLen is a slow initialization with the form `vec.set_len(..)`
+    UnsafeSetLen(&'tcx Expr),
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
@@ -93,7 +96,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                     len_expr: len_arg,
                 };
 
-                Pass::search_slow_zero_filling(cx, vi, expr.id, expr.span);
+                Pass::search_slow_initialization(cx, vi, expr.id, expr.span);
             }
         }
     }
@@ -114,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
                     len_expr: len_arg,
                 };
 
-                Pass::search_slow_zero_filling(cx, vi, stmt.node.id(), stmt.span);
+                Pass::search_slow_initialization(cx, vi, stmt.node.id(), stmt.span);
             }
         }
     }
@@ -138,8 +141,8 @@ impl Pass {
         None
     }
 
-    /// Search for slow zero filling vector initialization for the given vector
-    fn search_slow_zero_filling<'tcx>(
+    /// Search a slow initialization for the given vector
+    fn search_slow_initialization<'tcx>(
         cx: &LateContext<'_, 'tcx>,
         vec_initialization: VecInitialization<'tcx>,
         parent_node: NodeId,
@@ -171,11 +174,14 @@ impl Pass {
 
                     match repeat_expr {
                         InitializationType::Extend(e) => {
-                            db.span_note(e.span, "extended here with .. 0");
+                            db.span_note(e.span, "extended at");
                         },
                         InitializationType::Resize(e) => {
-                            db.span_note(e.span, "resize here with .. 0");
-                        }
+                            db.span_note(e.span, "resized at");
+                        },
+                        InitializationType::UnsafeSetLen(e) => {
+                            db.span_note(e.span, "changed len at");
+                        },
                     }
                 }
             );
@@ -239,6 +245,25 @@ impl<'a, 'tcx> SlowInitializationVisitor<'a, 'tcx> {
         }
     }
 
+    /// Checks if the given expression is using `set_len` to initialize the vector
+    fn search_unsafe_set_len(&mut self, expr: &'tcx Expr) {
+        if_chain! {
+            if self.initialization_found;
+            if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
+            if let ExprKind::Path(ref qpath_subj) = args[0].node;
+            if match_qpath(&qpath_subj, &[&self.vec_ini.variable_name.to_string()]);
+            if path.ident.name == "set_len";
+            if let Some(ref len_arg) = args.get(1);
+
+            // Check that len expression is equals to `with_capacity` expression
+            if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_ini.len_expr);
+
+            then {
+                self.slow_expression = Some(InitializationType::UnsafeSetLen(expr));
+            }
+        }
+    }
+
     /// Returns `true` if give expression is `repeat(0).take(...)`
     fn is_repeat_take(&self, expr: &Expr) -> bool {
         if_chain! {
@@ -294,6 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SlowInitializationVisitor<'a, 'tcx> {
         
         self.search_slow_extend_filling(expr);
         self.search_slow_resize_filling(expr);
+        self.search_unsafe_set_len(expr);
 
         walk_expr(self, expr);
     }
diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs
index f79abe8327e..991d850464e 100644
--- a/tests/ui/slow_vector_initialization.rs
+++ b/tests/ui/slow_vector_initialization.rs
@@ -13,6 +13,7 @@ fn main() {
     resize_vector();
     extend_vector();
     mixed_extend_resize_vector();
+    unsafe_vector();
 }
 
 fn extend_vector() {
@@ -61,3 +62,11 @@ fn resize_vector() {
     vec1 = Vec::with_capacity(10);
     vec1.resize(10, 0);
 }
+
+fn unsafe_vector() {
+    let mut unsafe_vec: Vec<u8> = Vec::with_capacity(200);
+
+    unsafe {
+        unsafe_vec.set_len(200);
+    }
+}
diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr
index 4941794d541..ece6f388c84 100644
--- a/tests/ui/slow_vector_initialization.stderr
+++ b/tests/ui/slow_vector_initialization.stderr
@@ -1,101 +1,115 @@
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:21:5
+  --> $DIR/slow_vector_initialization.rs:22:5
    |
-21 |     let mut vec1 = Vec::with_capacity(len);
+22 |     let mut vec1 = Vec::with_capacity(len);
    |     ^^^^^^^^^^^^^^^-----------------------^
    |                    |
    |                    help: consider replacing with: `vec![0; ..]`
    |
    = note: `-D clippy::slow-vector-initialization` implied by `-D warnings`
-note: extended here with .. 0
-  --> $DIR/slow_vector_initialization.rs:22:5
+note: extended at
+  --> $DIR/slow_vector_initialization.rs:23:5
    |
-22 |     vec1.extend(repeat(0).take(len));
+23 |     vec1.extend(repeat(0).take(len));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:25:5
+  --> $DIR/slow_vector_initialization.rs:26:5
    |
-25 |     let mut vec2 = Vec::with_capacity(len - 10);
+26 |     let mut vec2 = Vec::with_capacity(len - 10);
    |     ^^^^^^^^^^^^^^^----------------------------^
    |                    |
    |                    help: consider replacing with: `vec![0; ..]`
    |
-note: extended here with .. 0
-  --> $DIR/slow_vector_initialization.rs:26:5
+note: extended at
+  --> $DIR/slow_vector_initialization.rs:27:5
    |
-26 |     vec2.extend(repeat(0).take(len - 10));
+27 |     vec2.extend(repeat(0).take(len - 10));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:38:5
+  --> $DIR/slow_vector_initialization.rs:39:5
    |
-38 |     let mut resized_vec = Vec::with_capacity(30);
+39 |     let mut resized_vec = Vec::with_capacity(30);
    |     ^^^^^^^^^^^^^^^^^^^^^^----------------------^
    |                           |
    |                           help: consider replacing with: `vec![0; ..]`
    |
-note: resize here with .. 0
-  --> $DIR/slow_vector_initialization.rs:41:5
+note: resized at
+  --> $DIR/slow_vector_initialization.rs:42:5
    |
-41 |     resized_vec.resize(30, 0);
+42 |     resized_vec.resize(30, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:39:5
+  --> $DIR/slow_vector_initialization.rs:40:5
    |
-39 |     let mut extend_vec = Vec::with_capacity(30);
+40 |     let mut extend_vec = Vec::with_capacity(30);
    |     ^^^^^^^^^^^^^^^^^^^^^----------------------^
    |                          |
    |                          help: consider replacing with: `vec![0; ..]`
    |
-note: extended here with .. 0
-  --> $DIR/slow_vector_initialization.rs:43:5
+note: extended at
+  --> $DIR/slow_vector_initialization.rs:44:5
    |
-43 |     extend_vec.extend(repeat(0).take(30));
+44 |     extend_vec.extend(repeat(0).take(30));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:49:5
+  --> $DIR/slow_vector_initialization.rs:50:5
    |
-49 |     let mut vec1 = Vec::with_capacity(len);
+50 |     let mut vec1 = Vec::with_capacity(len);
    |     ^^^^^^^^^^^^^^^-----------------------^
    |                    |
    |                    help: consider replacing with: `vec![0; ..]`
    |
-note: resize here with .. 0
-  --> $DIR/slow_vector_initialization.rs:50:5
+note: resized at
+  --> $DIR/slow_vector_initialization.rs:51:5
    |
-50 |     vec1.resize(len, 0);
+51 |     vec1.resize(len, 0);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:57:5
+  --> $DIR/slow_vector_initialization.rs:58:5
    |
-57 |     let mut vec3 = Vec::with_capacity(len - 10);
+58 |     let mut vec3 = Vec::with_capacity(len - 10);
    |     ^^^^^^^^^^^^^^^----------------------------^
    |                    |
    |                    help: consider replacing with: `vec![0; ..]`
    |
-note: resize here with .. 0
-  --> $DIR/slow_vector_initialization.rs:58:5
+note: resized at
+  --> $DIR/slow_vector_initialization.rs:59:5
    |
-58 |     vec3.resize(len - 10, 0);
+59 |     vec3.resize(len - 10, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: detected slow zero-filling initialization
-  --> $DIR/slow_vector_initialization.rs:61:5
+  --> $DIR/slow_vector_initialization.rs:62:5
    |
-61 |     vec1 = Vec::with_capacity(10);
+62 |     vec1 = Vec::with_capacity(10);
    |     ^^^^^^^----------------------
    |            |
    |            help: consider replacing with: `vec![0; ..]`
    |
-note: resize here with .. 0
-  --> $DIR/slow_vector_initialization.rs:62:5
+note: resized at
+  --> $DIR/slow_vector_initialization.rs:63:5
    |
-62 |     vec1.resize(10, 0);
+63 |     vec1.resize(10, 0);
    |     ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: detected slow zero-filling initialization
+  --> $DIR/slow_vector_initialization.rs:67:5
+   |
+67 |     let mut unsafe_vec: Vec<u8> = Vec::with_capacity(200);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------^
+   |                                   |
+   |                                   help: consider replacing with: `vec![0; ..]`
+   |
+note: changed len at
+  --> $DIR/slow_vector_initialization.rs:70:9
+   |
+70 |         unsafe_vec.set_len(200);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors