about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/manual_unwrap_or_default.rs9
-rw-r--r--tests/ui/manual_unwrap_or_default.fixed10
-rw-r--r--tests/ui/manual_unwrap_or_default.rs10
-rw-r--r--tests/ui/manual_unwrap_or_default.stderr2
4 files changed, 30 insertions, 1 deletions
diff --git a/clippy_lints/src/manual_unwrap_or_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs
index c562ceb5bce..a4048e89926 100644
--- a/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/clippy_lints/src/manual_unwrap_or_default.rs
@@ -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;
 
@@ -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
@@ -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
diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed
index a0b707628a8..d6e736ba9cc 100644
--- a/tests/ui/manual_unwrap_or_default.fixed
+++ b/tests/ui/manual_unwrap_or_default.fixed
@@ -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
diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs
index 1d4cca12f6c..462d5d90ee7 100644
--- a/tests/ui/manual_unwrap_or_default.rs
+++ b/tests/ui/manual_unwrap_or_default.rs
@@ -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
diff --git a/tests/ui/manual_unwrap_or_default.stderr b/tests/ui/manual_unwrap_or_default.stderr
index d89212e6045..3f1da444301 100644
--- a/tests/ui/manual_unwrap_or_default.stderr
+++ b/tests/ui/manual_unwrap_or_default.stderr
@@ -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 {
    |  ____________________^