about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/dogfood.rs4
-rw-r--r--tests/ui/nonminimal_bool.rs29
-rw-r--r--tests/ui/redundant_async_block.fixed47
-rw-r--r--tests/ui/redundant_async_block.rs47
-rw-r--r--tests/ui/redundant_async_block.stderr22
-rw-r--r--tests/ui/uninit.rs23
-rw-r--r--tests/ui/uninit.stderr12
-rw-r--r--tests/ui/uninit_vec.rs27
-rw-r--r--tests/ui/uninit_vec.stderr33
9 files changed, 216 insertions, 28 deletions
diff --git a/tests/dogfood.rs b/tests/dogfood.rs
index 9643c2c9707..3a5d478fa31 100644
--- a/tests/dogfood.rs
+++ b/tests/dogfood.rs
@@ -37,10 +37,10 @@ fn dogfood_clippy() {
     }
 
     assert!(
-        !failed_packages.is_empty(),
+        failed_packages.is_empty(),
         "Dogfood failed for packages `{}`",
         failed_packages.iter().format(", "),
-    )
+    );
 }
 
 #[test]
diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs
index e9b4367ca65..3b5a374b4a7 100644
--- a/tests/ui/nonminimal_bool.rs
+++ b/tests/ui/nonminimal_bool.rs
@@ -63,3 +63,32 @@ fn issue9428() {
         println!("foo");
     }
 }
+
+fn issue_10523() {
+    macro_rules! a {
+        ($v:expr) => {
+            $v.is_some()
+        };
+    }
+    let x: Option<u32> = None;
+    if !a!(x) {}
+}
+
+fn issue_10523_1() {
+    macro_rules! a {
+        ($v:expr) => {
+            !$v.is_some()
+        };
+    }
+    let x: Option<u32> = None;
+    if a!(x) {}
+}
+
+fn issue_10523_2() {
+    macro_rules! a {
+        () => {
+            !None::<u32>.is_some()
+        };
+    }
+    if a!() {}
+}
diff --git a/tests/ui/redundant_async_block.fixed b/tests/ui/redundant_async_block.fixed
index 5f9931df45e..d26b7a332cb 100644
--- a/tests/ui/redundant_async_block.fixed
+++ b/tests/ui/redundant_async_block.fixed
@@ -3,6 +3,8 @@
 #![allow(unused)]
 #![warn(clippy::redundant_async_block)]
 
+use std::future::Future;
+
 async fn func1(n: usize) -> usize {
     n + 1
 }
@@ -62,3 +64,48 @@ fn main() {
     let fut = async_await_parameter_in_macro!(func2());
     let fut = async_await_in_macro!(std::convert::identity);
 }
+
+#[allow(clippy::let_and_return)]
+fn capture_local() -> impl Future<Output = i32> {
+    // Lint
+    let fut = async { 17 };
+    fut
+}
+
+fn capture_local_closure(s: &str) -> impl Future<Output = &str> {
+    let f = move || std::future::ready(s);
+    // Do not lint: `f` would not live long enough
+    async move { f().await }
+}
+
+#[allow(clippy::let_and_return)]
+fn capture_arg(s: &str) -> impl Future<Output = &str> {
+    // Lint
+    let fut = async move { s };
+    fut
+}
+
+#[derive(Debug, Clone)]
+struct F {}
+
+impl F {
+    async fn run(&self) {}
+}
+
+pub async fn run() {
+    let f = F {};
+    let c = f.clone();
+    // Do not lint: `c` would not live long enough
+    spawn(async move { c.run().await });
+    let _f = f;
+}
+
+fn spawn<F: Future + 'static>(_: F) {}
+
+async fn work(_: &str) {}
+
+fn capture() {
+    let val = "Hello World".to_owned();
+    // Do not lint: `val` would not live long enough
+    spawn(async { work(&{ val }).await });
+}
diff --git a/tests/ui/redundant_async_block.rs b/tests/ui/redundant_async_block.rs
index de3c9970c65..04726e62805 100644
--- a/tests/ui/redundant_async_block.rs
+++ b/tests/ui/redundant_async_block.rs
@@ -3,6 +3,8 @@
 #![allow(unused)]
 #![warn(clippy::redundant_async_block)]
 
+use std::future::Future;
+
 async fn func1(n: usize) -> usize {
     n + 1
 }
@@ -62,3 +64,48 @@ fn main() {
     let fut = async_await_parameter_in_macro!(func2());
     let fut = async_await_in_macro!(std::convert::identity);
 }
+
+#[allow(clippy::let_and_return)]
+fn capture_local() -> impl Future<Output = i32> {
+    // Lint
+    let fut = async { 17 };
+    async move { fut.await }
+}
+
+fn capture_local_closure(s: &str) -> impl Future<Output = &str> {
+    let f = move || std::future::ready(s);
+    // Do not lint: `f` would not live long enough
+    async move { f().await }
+}
+
+#[allow(clippy::let_and_return)]
+fn capture_arg(s: &str) -> impl Future<Output = &str> {
+    // Lint
+    let fut = async move { s };
+    async move { fut.await }
+}
+
+#[derive(Debug, Clone)]
+struct F {}
+
+impl F {
+    async fn run(&self) {}
+}
+
+pub async fn run() {
+    let f = F {};
+    let c = f.clone();
+    // Do not lint: `c` would not live long enough
+    spawn(async move { c.run().await });
+    let _f = f;
+}
+
+fn spawn<F: Future + 'static>(_: F) {}
+
+async fn work(_: &str) {}
+
+fn capture() {
+    let val = "Hello World".to_owned();
+    // Do not lint: `val` would not live long enough
+    spawn(async { work(&{ val }).await });
+}
diff --git a/tests/ui/redundant_async_block.stderr b/tests/ui/redundant_async_block.stderr
index b16d96dce84..1a1c1603e08 100644
--- a/tests/ui/redundant_async_block.stderr
+++ b/tests/ui/redundant_async_block.stderr
@@ -1,5 +1,5 @@
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:13:13
+  --> $DIR/redundant_async_block.rs:15:13
    |
 LL |     let x = async { f.await };
    |             ^^^^^^^^^^^^^^^^^ help: you can reduce it to: `f`
@@ -7,22 +7,34 @@ LL |     let x = async { f.await };
    = note: `-D clippy::redundant-async-block` implied by `-D warnings`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:46:16
+  --> $DIR/redundant_async_block.rs:48:16
    |
 LL |     let fut2 = async { fut1.await };
    |                ^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:49:16
+  --> $DIR/redundant_async_block.rs:51:16
    |
 LL |     let fut2 = async move { fut1.await };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:51:15
+  --> $DIR/redundant_async_block.rs:53:15
    |
 LL |     let fut = async { async { 42 }.await };
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }`
 
-error: aborting due to 4 previous errors
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:72:5
+   |
+LL |     async move { fut.await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut`
+
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:85:5
+   |
+LL |     async move { fut.await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut`
+
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs
index 21131731708..412b36b4ee8 100644
--- a/tests/ui/uninit.rs
+++ b/tests/ui/uninit.rs
@@ -3,13 +3,15 @@
 
 use std::mem::{self, MaybeUninit};
 
+union MyOwnMaybeUninit {
+    value: u8,
+    uninit: (),
+}
+
 fn main() {
     let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
 
-    // edge case: For now we lint on empty arrays
-    let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() };
-
-    // edge case: For now we accept unit tuples
+    // This is OK, because ZSTs do not contain data.
     let _: () = unsafe { MaybeUninit::uninit().assume_init() };
 
     // This is OK, because `MaybeUninit` allows uninitialized data.
@@ -21,6 +23,19 @@ fn main() {
     // This is OK, because all constitutent types are uninit-compatible.
     let _: (MaybeUninit<usize>, [MaybeUninit<bool>; 2]) = unsafe { MaybeUninit::uninit().assume_init() };
 
+    // This is OK, because our own MaybeUninit is just as fine as the one from core.
+    let _: MyOwnMaybeUninit = unsafe { MaybeUninit::uninit().assume_init() };
+
+    // This is OK, because empty arrays don't contain data.
+    let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() };
+
     // Was a false negative.
     let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() };
+
+    polymorphic::<()>();
+
+    fn polymorphic<T>() {
+        // We are conservative around polymorphic types.
+        let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() };
+    }
 }
diff --git a/tests/ui/uninit.stderr b/tests/ui/uninit.stderr
index 15ef2349489..9e01b9a4aa8 100644
--- a/tests/ui/uninit.stderr
+++ b/tests/ui/uninit.stderr
@@ -1,5 +1,5 @@
 error: this call for this type may be undefined behavior
-  --> $DIR/uninit.rs:7:29
+  --> $DIR/uninit.rs:12:29
    |
 LL |     let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,15 +7,15 @@ LL |     let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
    = note: `#[deny(clippy::uninit_assumed_init)]` on by default
 
 error: this call for this type may be undefined behavior
-  --> $DIR/uninit.rs:10:31
+  --> $DIR/uninit.rs:33:29
    |
-LL |     let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() };
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() };
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call for this type may be undefined behavior
-  --> $DIR/uninit.rs:25:29
+  --> $DIR/uninit.rs:39:29
    |
-LL |     let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() };
+LL |         let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() };
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs
index 194e4fc157e..59ec64a7ab1 100644
--- a/tests/ui/uninit_vec.rs
+++ b/tests/ui/uninit_vec.rs
@@ -7,6 +7,11 @@ struct MyVec {
     vec: Vec<u8>,
 }
 
+union MyOwnMaybeUninit {
+    value: u8,
+    uninit: (),
+}
+
 fn main() {
     // with_capacity() -> set_len() should be detected
     let mut vec: Vec<u8> = Vec::with_capacity(1000);
@@ -97,4 +102,26 @@ fn main() {
     unsafe {
         vec.set_len(0);
     }
+
+    // ZSTs should not be detected
+    let mut vec: Vec<()> = Vec::with_capacity(1000);
+    unsafe {
+        vec.set_len(10);
+    }
+
+    // unions should not be detected
+    let mut vec: Vec<MyOwnMaybeUninit> = Vec::with_capacity(1000);
+    unsafe {
+        vec.set_len(10);
+    }
+
+    polymorphic::<()>();
+
+    fn polymorphic<T>() {
+        // We are conservative around polymorphic types.
+        let mut vec: Vec<T> = Vec::with_capacity(1000);
+        unsafe {
+            vec.set_len(10);
+        }
+    }
 }
diff --git a/tests/ui/uninit_vec.stderr b/tests/ui/uninit_vec.stderr
index 77fc689f076..9cdf0c95ad9 100644
--- a/tests/ui/uninit_vec.stderr
+++ b/tests/ui/uninit_vec.stderr
@@ -1,5 +1,5 @@
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:12:5
+  --> $DIR/uninit_vec.rs:17:5
    |
 LL |     let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL |         vec.set_len(200);
    = note: `-D clippy::uninit-vec` implied by `-D warnings`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:18:5
+  --> $DIR/uninit_vec.rs:23:5
    |
 LL |     vec.reserve(1000);
    |     ^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> $DIR/uninit_vec.rs:24:5
+  --> $DIR/uninit_vec.rs:29:5
    |
 LL |     let mut vec: Vec<u8> = Vec::new();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> $DIR/uninit_vec.rs:30:5
+  --> $DIR/uninit_vec.rs:35:5
    |
 LL |     let mut vec: Vec<u8> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` on empty `Vec` creates out-of-bound values
-  --> $DIR/uninit_vec.rs:35:5
+  --> $DIR/uninit_vec.rs:40:5
    |
 LL |     let mut vec: Vec<u8> = Vec::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |         vec.set_len(200);
    |         ^^^^^^^^^^^^^^^^
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:49:5
+  --> $DIR/uninit_vec.rs:54:5
    |
 LL |     let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:58:5
+  --> $DIR/uninit_vec.rs:63:5
    |
 LL |     my_vec.vec.reserve(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL |         my_vec.vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:63:5
+  --> $DIR/uninit_vec.rs:68:5
    |
 LL |     my_vec.vec = Vec::with_capacity(1000);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -82,7 +82,7 @@ LL |         my_vec.vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:42:9
+  --> $DIR/uninit_vec.rs:47:9
    |
 LL |         let mut vec: Vec<u8> = Vec::with_capacity(1000);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,7 +92,7 @@ LL |         vec.set_len(200);
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
 error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
-  --> $DIR/uninit_vec.rs:45:9
+  --> $DIR/uninit_vec.rs:50:9
    |
 LL |         vec.reserve(1000);
    |         ^^^^^^^^^^^^^^^^^^
@@ -101,5 +101,16 @@ LL |         vec.set_len(200);
    |
    = help: initialize the buffer or wrap the content in `MaybeUninit`
 
-error: aborting due to 10 previous errors
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+  --> $DIR/uninit_vec.rs:122:9
+   |
+LL |         let mut vec: Vec<T> = Vec::with_capacity(1000);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         unsafe {
+LL |             vec.set_len(10);
+   |             ^^^^^^^^^^^^^^^
+   |
+   = help: initialize the buffer or wrap the content in `MaybeUninit`
+
+error: aborting due to 11 previous errors