Skip to content

Commit

Permalink
Check for Default trait in initial expression
Browse files Browse the repository at this point in the history
  • Loading branch information
ARandomDev99 committed Apr 1, 2024
1 parent c2681f2 commit 6a6a917
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 1 deletion.
9 changes: 9 additions & 0 deletions clippy_lints/src/manual_unwrap_or_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::GenericArgKind;
use rustc_session::declare_lint_pass;
use rustc_span::sym;

Expand Down Expand Up @@ -118,6 +119,10 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
&& implements_trait(cx, match_ty, default_trait_id, &[])
// We now get the bodies for both the `Some` and `None` arms.
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
// We check that the initial expression also implies the `Default` trait.
&& let Some(match_expr_ty) = cx.typeck_results().expr_ty(match_expr).walk().nth(1)
&& let GenericArgKind::Type(match_expr_ty) = match_expr_ty.unpack()
&& implements_trait(cx, match_expr_ty, default_trait_id, &[])
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(body_some).kind
&& let Res::Local(local_id) = path.res
Expand Down Expand Up @@ -154,6 +159,10 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
&& let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default)
&& implements_trait(cx, match_ty, default_trait_id, &[])
&& let Some(binding_id) = get_some(cx, let_.pat)
// We check that the initial expression also implies the `Default` trait.
&& let Some(let_ty) = cx.typeck_results().expr_ty(let_.init).walk().nth(1)
&& let GenericArgKind::Type(let_ty) = let_ty.unpack()
&& implements_trait(cx, let_ty, default_trait_id, &[])
// We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`.
&& let ExprKind::Path(QPath::Resolved(_, path)) = peel_blocks(if_block).kind
&& let Res::Local(local_id) = path.res
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/manual_unwrap_or_default.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ fn main() {

let x: Option<Vec<String>> = None;
x.unwrap_or_default();

// Issue #12564
// No error as &Vec<_> doesn't implement std::default::Default
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
// Same code as above written using match.
let x: &[_] = match map.get(&0) {
Some(x) => x,
None => &[],
};
}

// Issue #12531
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/manual_unwrap_or_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ fn main() {
} else {
Vec::default()
};

// Issue #12564
// No error as &Vec<_> doesn't implement std::default::Default
let mut map = std::collections::HashMap::from([(0, vec![0; 3]), (1, vec![1; 3]), (2, vec![2])]);
let x: &[_] = if let Some(x) = map.get(&0) { x } else { &[] };
// Same code as above written using match.
let x: &[_] = match map.get(&0) {
Some(x) => x,
None => &[],
};
}

// Issue #12531
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/manual_unwrap_or_default.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ LL | | };
| |_____^ help: replace it with: `x.unwrap_or_default()`

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

0 comments on commit 6a6a917

Please sign in to comment.