account for autoderef in eager_or_lazy

This commit is contained in:
y21 2023-06-05 23:45:18 +02:00
parent b033883e2b
commit e70dd55fd6
4 changed files with 81 additions and 36 deletions

View File

@ -15,6 +15,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, PredicateKind};
use rustc_span::{sym, Symbol};
use std::cmp;
@ -114,6 +115,20 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
if self.eagerness == ForceNoChange {
return;
}
// Autoderef through a user-defined `Deref` impl can have side-effects,
// so don't suggest changing it.
if self
.cx
.typeck_results()
.expr_adjustments(e)
.iter()
.any(|adj| matches!(adj.kind, Adjust::Deref(Some(_))))
{
self.eagerness |= NoChange;
return;
}
match e.kind {
ExprKind::Call(
&Expr {

View File

@ -4,6 +4,7 @@
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
#![allow(clippy::needless_borrow)]
use std::ops::Deref;
@ -81,6 +82,9 @@ fn main() {
let _ = Some(1).unwrap_or(*r);
let b = Box::new(1);
let _ = Some(1).unwrap_or(*b);
// Should lint - Builtin deref through autoderef
let _ = Some(1).as_ref().unwrap_or(&r);
let _ = Some(1).as_ref().unwrap_or(&b);
// Cases when unwrap is not called on a simple variable
let _ = Some(10).unwrap_or(2);
@ -113,6 +117,9 @@ fn main() {
let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl
let _ = Some(1).unwrap_or(*Issue10437);
let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437);
let _ = Some(1).as_ref().unwrap_or(&Issue10437);
// Should not lint - bool
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop

View File

@ -4,6 +4,7 @@
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
#![allow(clippy::needless_borrow)]
use std::ops::Deref;
@ -81,6 +82,9 @@ fn main() {
let _ = Some(1).unwrap_or_else(|| *r);
let b = Box::new(1);
let _ = Some(1).unwrap_or_else(|| *b);
// Should lint - Builtin deref through autoderef
let _ = Some(1).as_ref().unwrap_or_else(|| &r);
let _ = Some(1).as_ref().unwrap_or_else(|| &b);
// Cases when unwrap is not called on a simple variable
let _ = Some(10).unwrap_or_else(|| 2);
@ -113,6 +117,9 @@ fn main() {
let _ = Some(1).unwrap_or_else(|| *Issue10437); // Issue10437 has a deref impl
let _ = Some(1).unwrap_or(*Issue10437);
let _ = Some(1).as_ref().unwrap_or_else(|| &Issue10437);
let _ = Some(1).as_ref().unwrap_or(&Issue10437);
// Should not lint - bool
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop

View File

@ -1,5 +1,5 @@
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:67:13
--> $DIR/unnecessary_lazy_eval.rs:68: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:68:13
--> $DIR/unnecessary_lazy_eval.rs:69: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:69:13
--> $DIR/unnecessary_lazy_eval.rs:70: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:71:13
--> $DIR/unnecessary_lazy_eval.rs:72: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:72:13
--> $DIR/unnecessary_lazy_eval.rs:73: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:73:13
--> $DIR/unnecessary_lazy_eval.rs:74: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:74:13
--> $DIR/unnecessary_lazy_eval.rs:75: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:75:13
--> $DIR/unnecessary_lazy_eval.rs:76: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:76:13
--> $DIR/unnecessary_lazy_eval.rs:77: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:77:13
--> $DIR/unnecessary_lazy_eval.rs:78: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:81:13
--> $DIR/unnecessary_lazy_eval.rs:82:13
|
LL | let _ = Some(1).unwrap_or_else(|| *r);
| ^^^^^^^^---------------------
@ -89,7 +89,7 @@ LL | let _ = Some(1).unwrap_or_else(|| *r);
| help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:83:13
--> $DIR/unnecessary_lazy_eval.rs:84:13
|
LL | let _ = Some(1).unwrap_or_else(|| *b);
| ^^^^^^^^---------------------
@ -99,13 +99,29 @@ LL | let _ = Some(1).unwrap_or_else(|| *b);
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:86:13
|
LL | let _ = Some(1).as_ref().unwrap_or_else(|| &r);
| ^^^^^^^^^^^^^^^^^---------------------
| |
| help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:87:13
|
LL | let _ = Some(1).as_ref().unwrap_or_else(|| &b);
| ^^^^^^^^^^^^^^^^^---------------------
| |
| help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
error: unnecessary closure used to substitute value for `Option::None`
--> $DIR/unnecessary_lazy_eval.rs:90:13
|
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:87:13
--> $DIR/unnecessary_lazy_eval.rs:91:13
|
LL | let _ = Some(10).and_then(|_| ext_opt);
| ^^^^^^^^^---------------------
@ -113,7 +129,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:88:28
--> $DIR/unnecessary_lazy_eval.rs:92:28
|
LL | let _: Option<usize> = None.or_else(|| ext_opt);
| ^^^^^-------------------
@ -121,7 +137,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:89:13
--> $DIR/unnecessary_lazy_eval.rs:93:13
|
LL | let _ = None.get_or_insert_with(|| 2);
| ^^^^^------------------------
@ -129,7 +145,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:90:35
--> $DIR/unnecessary_lazy_eval.rs:94:35
|
LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
| ^^^^^----------------
@ -137,7 +153,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:91:28
--> $DIR/unnecessary_lazy_eval.rs:95:28
|
LL | let _: Option<usize> = None.or_else(|| None);
| ^^^^^----------------
@ -145,7 +161,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:94:13
--> $DIR/unnecessary_lazy_eval.rs:98:13
|
LL | let _ = deep.0.unwrap_or_else(|| 2);
| ^^^^^^^--------------------
@ -153,7 +169,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:95:13
--> $DIR/unnecessary_lazy_eval.rs:99:13
|
LL | let _ = deep.0.and_then(|_| ext_opt);
| ^^^^^^^---------------------
@ -161,7 +177,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:96:13
--> $DIR/unnecessary_lazy_eval.rs:100:13
|
LL | let _ = deep.0.or_else(|| None);
| ^^^^^^^----------------
@ -169,7 +185,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:97:13
--> $DIR/unnecessary_lazy_eval.rs:101:13
|
LL | let _ = deep.0.get_or_insert_with(|| 2);
| ^^^^^^^------------------------
@ -177,7 +193,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:98:13
--> $DIR/unnecessary_lazy_eval.rs:102:13
|
LL | let _ = deep.0.ok_or_else(|| 2);
| ^^^^^^^----------------
@ -185,7 +201,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:125:28
--> $DIR/unnecessary_lazy_eval.rs:132:28
|
LL | let _: Option<usize> = None.or_else(|| Some(3));
| ^^^^^-------------------
@ -193,7 +209,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:126:13
--> $DIR/unnecessary_lazy_eval.rs:133:13
|
LL | let _ = deep.0.or_else(|| Some(3));
| ^^^^^^^-------------------
@ -201,7 +217,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:127:13
--> $DIR/unnecessary_lazy_eval.rs:134:13
|
LL | let _ = opt.or_else(|| Some(3));
| ^^^^-------------------
@ -209,7 +225,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:133:13
--> $DIR/unnecessary_lazy_eval.rs:140:13
|
LL | let _ = res2.unwrap_or_else(|_| 2);
| ^^^^^---------------------
@ -217,7 +233,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:134:13
--> $DIR/unnecessary_lazy_eval.rs:141:13
|
LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
| ^^^^^----------------------------------
@ -225,7 +241,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:135:13
--> $DIR/unnecessary_lazy_eval.rs:142:13
|
LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
| ^^^^^--------------------------------------
@ -233,7 +249,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:157:35
--> $DIR/unnecessary_lazy_eval.rs:164:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
| ^^^^--------------------
@ -241,7 +257,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:158:35
--> $DIR/unnecessary_lazy_eval.rs:165:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
| ^^^^---------------------------------
@ -249,7 +265,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:159:35
--> $DIR/unnecessary_lazy_eval.rs:166:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
| ^^^^-------------------------------------
@ -257,7 +273,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:161:35
--> $DIR/unnecessary_lazy_eval.rs:168:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
| ^^^^------------------
@ -265,7 +281,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:162:35
--> $DIR/unnecessary_lazy_eval.rs:169:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
| ^^^^-------------------------------
@ -273,7 +289,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:163:35
--> $DIR/unnecessary_lazy_eval.rs:170:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
| ^^^^-----------------------------------
@ -281,7 +297,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:164:35
--> $DIR/unnecessary_lazy_eval.rs:171:35
|
LL | let _: Result<usize, usize> = res.
| ___________________________________^
@ -295,5 +311,5 @@ LL | | or_else(|_| Ok(ext_str.some_field));
| |
| help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
error: aborting due to 36 previous errors
error: aborting due to 38 previous errors