Skip to content

Commit 8529b2a

Browse files
committed
Auto merge of #8163 - pmnoxx:piotr-improve-unwrap-or-default, r=Manishearth
Improve `unwrap_or_else_default` when handling `unwrap_or_else(XXX::new)` changelog: change `unwrap_or_else_default` to work with std constructors like `Vec::new`, `HashSet::new`, `HashMap::new`. Notes: - Code to handle detecting those constructors is already there. I moved it out to `is_default_equivalent_call`
2 parents 9ae4043 + 2a47dbc commit 8529b2a

File tree

5 files changed

+42
-18
lines changed

5 files changed

+42
-18
lines changed

clippy_lints/src/methods/unwrap_or_else_default.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
use super::UNWRAP_OR_ELSE_DEFAULT;
44
use clippy_utils::{
5-
diagnostics::span_lint_and_sugg, is_trait_item, source::snippet_with_applicability, ty::is_type_diagnostic_item,
5+
diagnostics::span_lint_and_sugg, is_default_equivalent_call, source::snippet_with_applicability,
6+
ty::is_type_diagnostic_item,
67
};
78
use rustc_errors::Applicability;
89
use rustc_hir as hir;
@@ -24,7 +25,7 @@ pub(super) fn check<'tcx>(
2425

2526
if_chain! {
2627
if is_option || is_result;
27-
if is_trait_item(cx, u_arg, sym::Default);
28+
if is_default_equivalent_call(cx, u_arg);
2829
then {
2930
let mut applicability = Applicability::MachineApplicable;
3031

clippy_utils/src/lib.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,22 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
664664
false
665665
}
666666

667+
/// Return true if the expr is equal to `Default::default` when evaluated.
668+
pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> bool {
669+
if_chain! {
670+
if let hir::ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
671+
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
672+
if is_diag_trait_item(cx, repl_def_id, sym::Default)
673+
|| is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
674+
then {
675+
true
676+
}
677+
else {
678+
false
679+
}
680+
}
681+
}
682+
667683
/// Returns true if the expr is equal to `Default::default()` of it's type when evaluated.
668684
/// It doesn't cover all cases, for example indirect function calls (some of std
669685
/// functions are supported) but it is the best we have.
@@ -686,18 +702,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
686702
false
687703
}
688704
},
689-
ExprKind::Call(repl_func, _) => if_chain! {
690-
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
691-
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
692-
if is_diag_trait_item(cx, repl_def_id, sym::Default)
693-
|| is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
694-
then {
695-
true
696-
}
697-
else {
698-
false
699-
}
700-
},
705+
ExprKind::Call(repl_func, _) => is_default_equivalent_call(cx, repl_func),
701706
ExprKind::Path(qpath) => is_lang_ctor(cx, qpath, OptionNone),
702707
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
703708
_ => false,

tests/ui/unwrap_or_else_default.fixed

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn unwrap_or_else_default() {
4545
with_enum.unwrap_or_else(Enum::A);
4646

4747
let with_new = Some(vec![1]);
48-
with_new.unwrap_or_else(Vec::new);
48+
with_new.unwrap_or_default();
4949

5050
let with_err: Result<_, ()> = Ok(vec![1]);
5151
with_err.unwrap_or_else(make);
@@ -66,6 +66,9 @@ fn unwrap_or_else_default() {
6666

6767
let with_default_type = Some(1);
6868
with_default_type.unwrap_or_default();
69+
70+
let with_default_type: Option<Vec<u64>> = None;
71+
with_default_type.unwrap_or_default();
6972
}
7073

7174
fn main() {}

tests/ui/unwrap_or_else_default.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ fn unwrap_or_else_default() {
6666

6767
let with_default_type = Some(1);
6868
with_default_type.unwrap_or_else(u64::default);
69+
70+
let with_default_type: Option<Vec<u64>> = None;
71+
with_default_type.unwrap_or_else(Vec::new);
6972
}
7073

7174
fn main() {}

tests/ui/unwrap_or_else_default.stderr

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
error: use of `.unwrap_or_else(..)` to construct default value
2+
--> $DIR/unwrap_or_else_default.rs:48:5
3+
|
4+
LL | with_new.unwrap_or_else(Vec::new);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_new.unwrap_or_default()`
6+
|
7+
= note: `-D clippy::unwrap-or-else-default` implied by `-D warnings`
8+
19
error: use of `.unwrap_or_else(..)` to construct default value
210
--> $DIR/unwrap_or_else_default.rs:62:5
311
|
412
LL | with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
513
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_real_default.unwrap_or_default()`
6-
|
7-
= note: `-D clippy::unwrap-or-else-default` implied by `-D warnings`
814

915
error: use of `.unwrap_or_else(..)` to construct default value
1016
--> $DIR/unwrap_or_else_default.rs:65:5
@@ -18,5 +24,11 @@ error: use of `.unwrap_or_else(..)` to construct default value
1824
LL | with_default_type.unwrap_or_else(u64::default);
1925
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()`
2026

21-
error: aborting due to 3 previous errors
27+
error: use of `.unwrap_or_else(..)` to construct default value
28+
--> $DIR/unwrap_or_else_default.rs:71:5
29+
|
30+
LL | with_default_type.unwrap_or_else(Vec::new);
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()`
32+
33+
error: aborting due to 5 previous errors
2234

0 commit comments

Comments
 (0)