Skip to content

suggest passing function instead of calling it in closure for [option_if_let_else] #11460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion clippy_lints/src/option_if_let_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ fn try_get_option_occurrence<'tcx>(
}

let mut app = Applicability::Unspecified;

let (none_body, is_argless_call) = match none_body.kind {
ExprKind::Call(call_expr, []) if !none_body.span.from_expansion() => (call_expr, true),
_ => (none_body, false),
};

return Some(OptionOccurrence {
option: format_option_in_sugg(
Sugg::hir_with_context(cx, cond_expr, ctxt, "..", &mut app),
Expand All @@ -178,7 +184,7 @@ fn try_get_option_occurrence<'tcx>(
),
none_expr: format!(
"{}{}",
if method_sugg == "map_or" { "" } else if is_result { "|_| " } else { "|| "},
if method_sugg == "map_or" || is_argless_call { "" } else if is_result { "|_| " } else { "|| "},
Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
),
});
Expand Down
17 changes: 15 additions & 2 deletions tests/ui/option_if_let_else.fixed
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![warn(clippy::option_if_let_else)]
#![allow(
unused_tuple_struct_fields,
clippy::redundant_closure,
clippy::ref_option_ref,
clippy::equatable_if_let,
clippy::let_unit_value,
Expand Down Expand Up @@ -52,7 +51,7 @@ fn impure_else(arg: Option<i32>) {
println!("return 1");
1
};
let _ = arg.map_or_else(|| side_effect(), |x| x);
let _ = arg.map_or_else(side_effect, |x| x);
}

fn test_map_or_else(arg: Option<u32>) {
Expand Down Expand Up @@ -224,3 +223,17 @@ mod issue10729 {
fn do_something(_value: &str) {}
fn do_something2(_value: &mut str) {}
}

fn issue11429() {
use std::collections::HashMap;

macro_rules! new_map {
() => {{ HashMap::new() }};
}

let opt: Option<HashMap<u8, u8>> = None;

let mut _hashmap = opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone());

let mut _hm = opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone());
}
19 changes: 18 additions & 1 deletion tests/ui/option_if_let_else.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![warn(clippy::option_if_let_else)]
#![allow(
unused_tuple_struct_fields,
clippy::redundant_closure,
clippy::ref_option_ref,
clippy::equatable_if_let,
clippy::let_unit_value,
Expand Down Expand Up @@ -271,3 +270,21 @@ mod issue10729 {
fn do_something(_value: &str) {}
fn do_something2(_value: &mut str) {}
}

fn issue11429() {
use std::collections::HashMap;

macro_rules! new_map {
() => {{ HashMap::new() }};
}

let opt: Option<HashMap<u8, u8>> = None;

let mut _hashmap = if let Some(hm) = &opt {
hm.clone()
} else {
HashMap::new()
};

let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() };
}
67 changes: 42 additions & 25 deletions tests/ui/option_if_let_else.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:12:5
--> $DIR/option_if_let_else.rs:11:5
|
LL | / if let Some(x) = string {
LL | | (true, x)
Expand All @@ -11,19 +11,19 @@ LL | | }
= note: `-D clippy::option-if-let-else` implied by `-D warnings`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:30:13
--> $DIR/option_if_let_else.rs:29:13
|
LL | let _ = if let Some(s) = *string { s.len() } else { 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:31:13
--> $DIR/option_if_let_else.rs:30:13
|
LL | let _ = if let Some(s) = &num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:32:13
--> $DIR/option_if_let_else.rs:31:13
|
LL | let _ = if let Some(s) = &mut num {
| _____________^
Expand All @@ -43,13 +43,13 @@ LL ~ });
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:38:13
--> $DIR/option_if_let_else.rs:37:13
|
LL | let _ = if let Some(ref s) = num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:39:13
--> $DIR/option_if_let_else.rs:38:13
|
LL | let _ = if let Some(mut s) = num {
| _____________^
Expand All @@ -69,7 +69,7 @@ LL ~ });
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:45:13
--> $DIR/option_if_let_else.rs:44:13
|
LL | let _ = if let Some(ref mut s) = num {
| _____________^
Expand All @@ -89,7 +89,7 @@ LL ~ });
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:54:5
--> $DIR/option_if_let_else.rs:53:5
|
LL | / if let Some(x) = arg {
LL | | let y = x * x;
Expand All @@ -108,7 +108,7 @@ LL + })
|

error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:67:13
--> $DIR/option_if_let_else.rs:66:13
|
LL | let _ = if let Some(x) = arg {
| _____________^
Expand All @@ -117,10 +117,10 @@ LL | | } else {
LL | | // map_or_else must be suggested
LL | | side_effect()
LL | | };
| |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
| |_____^ help: try: `arg.map_or_else(side_effect, |x| x)`

error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:76:13
--> $DIR/option_if_let_else.rs:75:13
|
LL | let _ = if let Some(x) = arg {
| _____________^
Expand All @@ -143,7 +143,7 @@ LL ~ }, |x| x * x * x * x);
|

error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:109:13
--> $DIR/option_if_let_else.rs:108:13
|
LL | / if let Some(idx) = s.find('.') {
LL | | vec![s[..idx].to_string(), s[idx..].to_string()]
Expand All @@ -153,7 +153,7 @@ LL | | }
| |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`

error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:120:5
--> $DIR/option_if_let_else.rs:119:5
|
LL | / if let Ok(binding) = variable {
LL | | println!("Ok {binding}");
Expand All @@ -172,13 +172,13 @@ LL + })
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:142:13
--> $DIR/option_if_let_else.rs:141:13
|
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:152:13
--> $DIR/option_if_let_else.rs:151:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
Expand All @@ -200,13 +200,13 @@ LL ~ });
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:180:13
--> $DIR/option_if_let_else.rs:179:13
|
LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:184:13
--> $DIR/option_if_let_else.rs:183:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
Expand All @@ -226,7 +226,7 @@ LL ~ });
|

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:223:13
--> $DIR/option_if_let_else.rs:222:13
|
LL | let _ = match s {
| _____________^
Expand All @@ -236,7 +236,7 @@ LL | | };
| |_____^ help: try: `s.map_or(1, |string| string.len())`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:227:13
--> $DIR/option_if_let_else.rs:226:13
|
LL | let _ = match Some(10) {
| _____________^
Expand All @@ -246,7 +246,7 @@ LL | | };
| |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:233:13
--> $DIR/option_if_let_else.rs:232:13
|
LL | let _ = match res {
| _____________^
Expand All @@ -256,7 +256,7 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:237:13
--> $DIR/option_if_let_else.rs:236:13
|
LL | let _ = match res {
| _____________^
Expand All @@ -266,13 +266,13 @@ LL | | };
| |_____^ help: try: `res.map_or(1, |a| a + 1)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:241:13
--> $DIR/option_if_let_else.rs:240:13
|
LL | let _ = if let Ok(a) = res { a + 1 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:258:9
--> $DIR/option_if_let_else.rs:257:9
|
LL | / match initial {
LL | | Some(value) => do_something(value),
Expand All @@ -281,13 +281,30 @@ LL | | }
| |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))`

error: use Option::map_or instead of an if let/else
--> $DIR/option_if_let_else.rs:265:9
--> $DIR/option_if_let_else.rs:264:9
|
LL | / match initial {
LL | | Some(value) => do_something2(value),
LL | | None => {},
LL | | }
| |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))`

error: aborting due to 23 previous errors
error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:283:24
|
LL | let mut _hashmap = if let Some(hm) = &opt {
| ________________________^
LL | | hm.clone()
LL | | } else {
LL | | HashMap::new()
LL | | };
| |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())`

error: use Option::map_or_else instead of an if let/else
--> $DIR/option_if_let_else.rs:289:19
|
LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())`

error: aborting due to 25 previous errors