Skip to content

Commit 6a6a917

Browse files
committed
Check for Default trait in initial expression
1 parent c2681f2 commit 6a6a917

File tree

4 files changed

+30
-1
lines changed

4 files changed

+30
-1
lines changed

clippy_lints/src/manual_unwrap_or_default.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_errors::Applicability;
33
use rustc_hir::def::Res;
44
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
55
use rustc_lint::{LateContext, LateLintPass, LintContext};
6+
use rustc_middle::ty::GenericArgKind;
67
use rustc_session::declare_lint_pass;
78
use rustc_span::sym;
89

@@ -118,6 +119,10 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
118119
&& implements_trait(cx, match_ty, default_trait_id, &[])
119120
// We now get the bodies for both the `Some` and `None` arms.
120121
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
122+
// We check that the initial expression also implies the `Default` trait.
123+
&& let Some(match_expr_ty) = cx.typeck_results().expr_ty(match_expr).walk().nth(1)
124+
&& let GenericArgKind::Type(match_expr_ty) = match_expr_ty.unpack()
125+
&& implements_trait(cx, match_expr_ty, default_trait_id, &[])
121126
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
122127
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
123128
&& let Res::Local(local_id) = path.res
@@ -154,6 +159,10 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
154159
&& let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
155160
&& implements_trait(cx, match_ty, default_trait_id, &[])
156161
&& let Some(binding_id) = get_some(cx, let_.pat)
162+
// We check that the initial expression also implies the `Default` trait.
163+
&& let Some(let_ty) = cx.typeck_results().expr_ty(let_.init).walk().nth(1)
164+
&& let GenericArgKind::Type(let_ty) = let_ty.unpack()
165+
&& implements_trait(cx, let_ty, default_trait_id, &[])
157166
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
158167
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
159168
&& let Res::Local(local_id) = path.res

tests/ui/manual_unwrap_or_default.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ fn main() {
1616

1717
let x: Option<Vec<String>> = None;
1818
x.unwrap_or_default();
19+
20+
// Issue #12564
21+
// No error as &Vec<_> doesn't implement std::default::Default
22+
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
23+
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
24+
// Same code as above written using match.
25+
let x: &[_] = match map.get(&0) {
26+
Some(x) => x,
27+
None => &[],
28+
};
1929
}
2030

2131
// Issue #12531

tests/ui/manual_unwrap_or_default.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ fn main() {
3737
} else {
3838
Vec::default()
3939
};
40+
41+
// Issue #12564
42+
// No error as &Vec<_> doesn't implement std::default::Default
43+
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
44+
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
45+
// Same code as above written using match.
46+
let x: &[_] = match map.get(&0) {
47+
Some(x) => x,
48+
None => &[],
49+
};
4050
}
4151

4252
// Issue #12531

tests/ui/manual_unwrap_or_default.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ LL | | };
5353
| |_____^ help: replace it with: `x.unwrap_or_default()`
5454

5555
error: match can be simplified with `.unwrap_or_default()`
56-
--> tests/ui/manual_unwrap_or_default.rs:46:20
56+
--> tests/ui/manual_unwrap_or_default.rs:56:20
5757
|
5858
LL | Some(_) => match *b {
5959
| ____________________^

0 commit comments

Comments
 (0)