about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2024-07-07 20:41:55 +0700
committerLzu Tao <taolzu@gmail.com>2024-07-07 20:41:55 +0700
commitc46c1f6da6725e0aa33e7738e9e0eb2f58b46eb6 (patch)
treecf1c1996c966bbf6fa4454f705798258f176c8f2
parente864519fbcaef5141e8fda7fdfac1a2c8d363cd2 (diff)
downloadrust-c46c1f6da6725e0aa33e7738e9e0eb2f58b46eb6.tar.gz
rust-c46c1f6da6725e0aa33e7738e9e0eb2f58b46eb6.zip
Fix 13018: self should be T
with `Option::unwrap_or(self, T) -> T`.
-rw-r--r--clippy_lints/src/matches/manual_unwrap_or.rs11
-rw-r--r--tests/ui/manual_unwrap_or.fixed9
-rw-r--r--tests/ui/manual_unwrap_or.rs11
-rw-r--r--tests/ui/manual_unwrap_or.stderr12
4 files changed, 27 insertions, 16 deletions
diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs
index 0940fc3219b..85a08f81c2f 100644
--- a/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -35,6 +35,17 @@ pub(super) fn check_if_let<'tcx>(
     else_expr: &'tcx Expr<'_>,
 ) {
     let ty = cx.typeck_results().expr_ty(let_expr);
+    let then_ty = cx.typeck_results().expr_ty(then_expr);
+    // The signature is `fn unwrap_or<T>(self: Option<T>, default: T) -> T`.
+    // When `expr_adjustments(then_expr).is_empty()`, `T` should equate to `default`'s type.
+    // Otherwise, type error will occur.
+    if cx.typeck_results().expr_adjustments(then_expr).is_empty()
+        && let rustc_middle::ty::Adt(_did, args) = ty.kind()
+        && let Some(some_ty) = args.first().and_then(|arg| arg.as_type())
+        && some_ty != then_ty
+    {
+        return;
+    }
     check_and_lint(cx, expr, let_pat, let_expr, then_expr, peel_blocks(else_expr), ty);
 }
 
diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed
index 2899c3518de..07e4bdd483a 100644
--- a/tests/ui/manual_unwrap_or.fixed
+++ b/tests/ui/manual_unwrap_or.fixed
@@ -239,7 +239,14 @@ mod issue_13018 {
 
     type RefName = i32;
     pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
-        index.get(&id).unwrap_or(&[])
+        if let Some(names) = index.get(&id) { names } else { &[] }
+    }
+
+    pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        match index.get(&id) {
+            Some(names) => names,
+            None => &[],
+        }
     }
 }
 
diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs
index e2c04b01ed9..cdbe51a4121 100644
--- a/tests/ui/manual_unwrap_or.rs
+++ b/tests/ui/manual_unwrap_or.rs
@@ -289,10 +289,13 @@ mod issue_13018 {
 
     type RefName = i32;
     pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
-        if let Some(names) = index.get(&id) {
-            names
-        } else {
-            &[]
+        if let Some(names) = index.get(&id) { names } else { &[] }
+    }
+
+    pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
+        match index.get(&id) {
+            Some(names) => names,
+            None => &[],
         }
     }
 }
diff --git a/tests/ui/manual_unwrap_or.stderr b/tests/ui/manual_unwrap_or.stderr
index 28b59df161d..c93a8952a08 100644
--- a/tests/ui/manual_unwrap_or.stderr
+++ b/tests/ui/manual_unwrap_or.stderr
@@ -172,15 +172,5 @@ LL | |             None => 0,
 LL | |         };
    | |_________^ help: replace with: `some_macro!().unwrap_or(0)`
 
-error: this pattern reimplements `Option::unwrap_or`
-  --> tests/ui/manual_unwrap_or.rs:292:9
-   |
-LL | /         if let Some(names) = index.get(&id) {
-LL | |             names
-LL | |         } else {
-LL | |             &[]
-LL | |         }
-   | |_________^ help: replace with: `index.get(&id).unwrap_or(&[])`
-
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors