about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkraktus <kraktus@users.noreply.github.com>2022-09-28 22:21:52 +0200
committerkraktus <kraktus@users.noreply.github.com>2022-09-28 22:46:05 +0200
commit314d57a7908d596a0fdfd58735bdc9e3727aed29 (patch)
treeb786c6a08005a3df1e44baa47b481a136d2bf715
parent8845f8214201bf8945de37997394994c5f6f7ace (diff)
downloadrust-314d57a7908d596a0fdfd58735bdc9e3727aed29.tar.gz
rust-314d57a7908d596a0fdfd58735bdc9e3727aed29.zip
[`unnecessary_lazy_evaluations`] Do not suggest switching to early evaluation when type has custom `Drop`
-rw-r--r--clippy_utils/src/eager_or_lazy.rs12
-rw-r--r--tests/ui/unnecessary_lazy_eval.fixed11
-rw-r--r--tests/ui/unnecessary_lazy_eval.rs11
-rw-r--r--tests/ui/unnecessary_lazy_eval.stderr68
4 files changed, 67 insertions, 35 deletions
diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs
index 91c9c382c23..8724a4cd651 100644
--- a/clippy_utils/src/eager_or_lazy.rs
+++ b/clippy_utils/src/eager_or_lazy.rs
@@ -113,7 +113,17 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                     },
                     args,
                 ) => match self.cx.qpath_res(path, hir_id) {
-                    Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => (),
+                    Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => {
+                        if self
+                            .cx
+                            .typeck_results()
+                            .expr_ty(e)
+                            .has_significant_drop(self.cx.tcx, self.cx.param_env)
+                        {
+                            self.eagerness = Lazy;
+                            return;
+                        }
+                    },
                     Res::Def(_, id) if self.cx.tcx.is_promotable_const_fn(id) => (),
                     // No need to walk the arguments here, `is_const_evaluatable` already did
                     Res::Def(..) if is_const_evaluatable(self.cx, e) => {
diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed
index eed81796883..878537050d4 100644
--- a/tests/ui/unnecessary_lazy_eval.fixed
+++ b/tests/ui/unnecessary_lazy_eval.fixed
@@ -21,6 +21,14 @@ fn some_call<T: Default>() -> T {
     T::default()
 }
 
+struct Issue9427(i32);
+
+impl Drop for Issue9427 {
+    fn drop(&mut self) {
+        println!("{}", self.0);
+    }
+}
+
 fn main() {
     let astronomers_pi = 10;
     let ext_arr: [usize; 1] = [2];
@@ -73,6 +81,9 @@ fn main() {
     let _ = deep.0.or_else(|| some_call());
     let _ = opt.ok_or_else(|| ext_arr[0]);
 
+    // Should not lint - bool
+    let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
+
     // should not lint, bind_instead_of_map takes priority
     let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
     let _ = Some(10).and_then(|idx| Some(idx));
diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs
index 1588db79b38..f70cf332460 100644
--- a/tests/ui/unnecessary_lazy_eval.rs
+++ b/tests/ui/unnecessary_lazy_eval.rs
@@ -21,6 +21,14 @@ fn some_call<T: Default>() -> T {
     T::default()
 }
 
+struct Issue9427(i32);
+
+impl Drop for Issue9427 {
+    fn drop(&mut self) {
+        println!("{}", self.0);
+    }
+}
+
 fn main() {
     let astronomers_pi = 10;
     let ext_arr: [usize; 1] = [2];
@@ -73,6 +81,9 @@ fn main() {
     let _ = deep.0.or_else(|| some_call());
     let _ = opt.ok_or_else(|| ext_arr[0]);
 
+    // Should not lint - bool
+    let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
+
     // should not lint, bind_instead_of_map takes priority
     let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
     let _ = Some(10).and_then(|idx| Some(idx));
diff --git a/tests/ui/unnecessary_lazy_eval.stderr b/tests/ui/unnecessary_lazy_eval.stderr
index 83dc7fd832c..b46fbf56c4b 100644
--- a/tests/ui/unnecessary_lazy_eval.stderr
+++ b/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:36:13
+  --> $DIR/unnecessary_lazy_eval.rs:44:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
    |             ^^^^--------------------
@@ -9,7 +9,7 @@ LL |     let _ = opt.unwrap_or_else(|| 2);
    = note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:37:13
+  --> $DIR/unnecessary_lazy_eval.rs:45:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |             ^^^^---------------------------------
@@ -17,7 +17,7 @@ LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:38:13
+  --> $DIR/unnecessary_lazy_eval.rs:46:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |             ^^^^-------------------------------------
@@ -25,7 +25,7 @@ LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:40:13
+  --> $DIR/unnecessary_lazy_eval.rs:48:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
    |             ^^^^---------------------
@@ -33,7 +33,7 @@ LL |     let _ = opt.and_then(|_| ext_opt);
    |                 help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:41:13
+  --> $DIR/unnecessary_lazy_eval.rs:49:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
    |             ^^^^-------------------
@@ -41,7 +41,7 @@ LL |     let _ = opt.or_else(|| ext_opt);
    |                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:42:13
+  --> $DIR/unnecessary_lazy_eval.rs:50:13
    |
 LL |     let _ = opt.or_else(|| None);
    |             ^^^^----------------
@@ -49,7 +49,7 @@ LL |     let _ = opt.or_else(|| None);
    |                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:43:13
+  --> $DIR/unnecessary_lazy_eval.rs:51:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
    |             ^^^^------------------------
@@ -57,7 +57,7 @@ LL |     let _ = opt.get_or_insert_with(|| 2);
    |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:44:13
+  --> $DIR/unnecessary_lazy_eval.rs:52:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
    |             ^^^^----------------
@@ -65,7 +65,7 @@ LL |     let _ = opt.ok_or_else(|| 2);
    |                 help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:45:13
+  --> $DIR/unnecessary_lazy_eval.rs:53:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |             ^^^^^^^^^^^^^^^^^-------------------------------
@@ -73,7 +73,7 @@ LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:46:13
+  --> $DIR/unnecessary_lazy_eval.rs:54:13
    |
 LL |     let _ = cond.then(|| astronomers_pi);
    |             ^^^^^-----------------------
@@ -81,7 +81,7 @@ LL |     let _ = cond.then(|| astronomers_pi);
    |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:49:13
+  --> $DIR/unnecessary_lazy_eval.rs:57:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |             ^^^^^^^^^--------------------
@@ -89,7 +89,7 @@ LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:50:13
+  --> $DIR/unnecessary_lazy_eval.rs:58:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
    |             ^^^^^^^^^---------------------
@@ -97,7 +97,7 @@ LL |     let _ = Some(10).and_then(|_| ext_opt);
    |                      help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:51:28
+  --> $DIR/unnecessary_lazy_eval.rs:59:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                            ^^^^^-------------------
@@ -105,7 +105,7 @@ LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:52:13
+  --> $DIR/unnecessary_lazy_eval.rs:60:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
    |             ^^^^^------------------------
@@ -113,7 +113,7 @@ LL |     let _ = None.get_or_insert_with(|| 2);
    |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:53:35
+  --> $DIR/unnecessary_lazy_eval.rs:61:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                   ^^^^^----------------
@@ -121,7 +121,7 @@ LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                        help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:54:28
+  --> $DIR/unnecessary_lazy_eval.rs:62:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
    |                            ^^^^^----------------
@@ -129,7 +129,7 @@ LL |     let _: Option<usize> = None.or_else(|| None);
    |                                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:57:13
+  --> $DIR/unnecessary_lazy_eval.rs:65:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |             ^^^^^^^--------------------
@@ -137,7 +137,7 @@ LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:58:13
+  --> $DIR/unnecessary_lazy_eval.rs:66:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
    |             ^^^^^^^---------------------
@@ -145,7 +145,7 @@ LL |     let _ = deep.0.and_then(|_| ext_opt);
    |                    help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:59:13
+  --> $DIR/unnecessary_lazy_eval.rs:67:13
    |
 LL |     let _ = deep.0.or_else(|| None);
    |             ^^^^^^^----------------
@@ -153,7 +153,7 @@ LL |     let _ = deep.0.or_else(|| None);
    |                    help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:60:13
+  --> $DIR/unnecessary_lazy_eval.rs:68:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |             ^^^^^^^------------------------
@@ -161,7 +161,7 @@ LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:61:13
+  --> $DIR/unnecessary_lazy_eval.rs:69:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
    |             ^^^^^^^----------------
@@ -169,7 +169,7 @@ LL |     let _ = deep.0.ok_or_else(|| 2);
    |                    help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:81:28
+  --> $DIR/unnecessary_lazy_eval.rs:92:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                            ^^^^^-------------------
@@ -177,7 +177,7 @@ LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:82:13
+  --> $DIR/unnecessary_lazy_eval.rs:93:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
    |             ^^^^^^^-------------------
@@ -185,7 +185,7 @@ LL |     let _ = deep.0.or_else(|| Some(3));
    |                    help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:83:13
+  --> $DIR/unnecessary_lazy_eval.rs:94:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
    |             ^^^^-------------------
@@ -193,7 +193,7 @@ LL |     let _ = opt.or_else(|| Some(3));
    |                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:89:13
+  --> $DIR/unnecessary_lazy_eval.rs:100:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
    |             ^^^^^---------------------
@@ -201,7 +201,7 @@ LL |     let _ = res2.unwrap_or_else(|_| 2);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:90:13
+  --> $DIR/unnecessary_lazy_eval.rs:101:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |             ^^^^^----------------------------------
@@ -209,7 +209,7 @@ LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:91:13
+  --> $DIR/unnecessary_lazy_eval.rs:102:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |             ^^^^^--------------------------------------
@@ -217,7 +217,7 @@ LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:113:35
+  --> $DIR/unnecessary_lazy_eval.rs:124:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                   ^^^^--------------------
@@ -225,7 +225,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                       help: use `and(..)` instead: `and(Err(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:114:35
+  --> $DIR/unnecessary_lazy_eval.rs:125:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                   ^^^^---------------------------------
@@ -233,7 +233,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:115:35
+  --> $DIR/unnecessary_lazy_eval.rs:126:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
    |                                   ^^^^-------------------------------------
@@ -241,7 +241,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
    |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:117:35
+  --> $DIR/unnecessary_lazy_eval.rs:128:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                   ^^^^------------------
@@ -249,7 +249,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                       help: use `or(..)` instead: `or(Ok(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:118:35
+  --> $DIR/unnecessary_lazy_eval.rs:129:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                   ^^^^-------------------------------
@@ -257,7 +257,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:119:35
+  --> $DIR/unnecessary_lazy_eval.rs:130:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                   ^^^^-----------------------------------
@@ -265,7 +265,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:120:35
+  --> $DIR/unnecessary_lazy_eval.rs:131:35
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^