Skip to content

Commit 7babd1b

Browse files
committed
Auto merge of #9421 - xphoniex:fix-#9420, r=giraffate
Suggest `unwrap_or_default` when closure returns `"".to_string` Closes rust-lang/rust-clippy#9420 changelog: [`unwrap_or_else_default`]: suggest `unwrap_or_default()` instead of `unwrap_or_else` with a closure that returns an empty `to_string`.
2 parents b763b14 + b21d9d3 commit 7babd1b

File tree

4 files changed

+35
-3
lines changed

4 files changed

+35
-3
lines changed

clippy_lints/src/methods/unwrap_or_else_default.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ use clippy_utils::{
55
diagnostics::span_lint_and_sugg, is_default_equivalent_call, source::snippet_with_applicability,
66
ty::is_type_diagnostic_item,
77
};
8+
use rustc_ast::ast::LitKind;
89
use rustc_errors::Applicability;
910
use rustc_hir as hir;
1011
use rustc_lint::LateContext;
11-
use rustc_span::sym;
12+
use rustc_span::{sym, symbol};
1213

1314
pub(super) fn check<'tcx>(
1415
cx: &LateContext<'tcx>,
@@ -25,7 +26,7 @@ pub(super) fn check<'tcx>(
2526

2627
if_chain! {
2728
if is_option || is_result;
28-
if is_default_equivalent_call(cx, u_arg);
29+
if closure_body_returns_empty_to_string(cx, u_arg) || is_default_equivalent_call(cx, u_arg);
2930
then {
3031
let mut applicability = Applicability::MachineApplicable;
3132

@@ -44,3 +45,22 @@ pub(super) fn check<'tcx>(
4445
}
4546
}
4647
}
48+
49+
fn closure_body_returns_empty_to_string(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> bool {
50+
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = e.kind {
51+
let body = cx.tcx.hir().body(body);
52+
53+
if body.params.is_empty()
54+
&& let hir::Expr{ kind, .. } = &body.value
55+
&& let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, [self_arg], _) = kind
56+
&& ident == &symbol::Ident::from_str("to_string")
57+
&& let hir::Expr{ kind, .. } = self_arg
58+
&& let hir::ExprKind::Lit(lit) = kind
59+
&& let LitKind::Str(symbol::kw::Empty, _) = lit.node
60+
{
61+
return true;
62+
}
63+
}
64+
65+
false
66+
}

tests/ui/unwrap_or_else_default.fixed

+3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ fn unwrap_or_else_default() {
6969

7070
let with_default_type: Option<Vec<u64>> = None;
7171
with_default_type.unwrap_or_default();
72+
73+
let empty_string = None::<String>;
74+
empty_string.unwrap_or_default();
7275
}
7376

7477
fn main() {}

tests/ui/unwrap_or_else_default.rs

+3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ fn unwrap_or_else_default() {
6969

7070
let with_default_type: Option<Vec<u64>> = None;
7171
with_default_type.unwrap_or_else(Vec::new);
72+
73+
let empty_string = None::<String>;
74+
empty_string.unwrap_or_else(|| "".to_string());
7275
}
7376

7477
fn main() {}

tests/ui/unwrap_or_else_default.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,11 @@ error: use of `.unwrap_or_else(..)` to construct default value
3030
LL | with_default_type.unwrap_or_else(Vec::new);
3131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()`
3232

33-
error: aborting due to 5 previous errors
33+
error: use of `.unwrap_or_else(..)` to construct default value
34+
--> $DIR/unwrap_or_else_default.rs:74:5
35+
|
36+
LL | empty_string.unwrap_or_else(|| "".to_string());
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `empty_string.unwrap_or_default()`
38+
39+
error: aborting due to 6 previous errors
3440

0 commit comments

Comments
 (0)