about summary refs log tree commit diff
diff options
context:
space:
mode:
authory21 <30553356+y21@users.noreply.github.com>2023-06-26 20:13:06 +0200
committery21 <30553356+y21@users.noreply.github.com>2023-06-26 20:13:06 +0200
commit733a9ea6b906441b755fbcd983c93a466b331070 (patch)
treee8c7bc8d4509de4865a9ae8188be41bf3e5a0426
parent8fd021f50456b777bf44c044ea5381c341d772c1 (diff)
downloadrust-733a9ea6b906441b755fbcd983c93a466b331070.tar.gz
rust-733a9ea6b906441b755fbcd983c93a466b331070.zip
[`option_if_let_else`]: suggest `.as_ref()` if `&Option<_>`
-rw-r--r--clippy_lints/src/option_if_let_else.rs3
-rw-r--r--tests/ui/option_if_let_else.fixed18
-rw-r--r--tests/ui/option_if_let_else.rs24
-rw-r--r--tests/ui/option_if_let_else.stderr20
4 files changed, 64 insertions, 1 deletions
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs
index aa6d4004268..abdccc47f54 100644
--- a/clippy_lints/src/option_if_let_else.rs
+++ b/clippy_lints/src/option_if_let_else.rs
@@ -140,6 +140,9 @@ fn try_get_option_occurrence<'tcx>(
             let (as_ref, as_mut) = match &expr.kind {
                 ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                 ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
+                _ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => {
+                    (mutb == Mutability::Not, mutb == Mutability::Mut)
+                }
                 _ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
             };
 
diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed
index 2b8ce5477cc..44ab8ebb50a 100644
--- a/tests/ui/option_if_let_else.fixed
+++ b/tests/ui/option_if_let_else.fixed
@@ -198,6 +198,8 @@ fn main() {
     let _ = res.map_or(1, |a| a + 1);
     let _ = res.map_or(1, |a| a + 1);
     let _ = res.map_or(5, |a| a + 1);
+    issue10729::reproduce(&None);
+    issue10729::reproduce2(&mut None);
 }
 
 #[allow(dead_code)]
@@ -208,3 +210,19 @@ fn issue9742() -> Option<&'static str> {
         _ => None,
     }
 }
+
+mod issue10729 {
+    #![allow(clippy::unit_arg)]
+
+    pub fn reproduce(initial: &Option<String>) {
+        // 👇 needs `.as_ref()` because initial is an `&Option<_>`
+        initial.as_ref().map_or({}, |value| do_something(value))
+    }
+
+    pub fn reproduce2(initial: &mut Option<String>) {
+        initial.as_mut().map_or({}, |value| do_something2(value))
+    }
+
+    fn do_something(_value: &str) {}
+    fn do_something2(_value: &mut str) {}
+}
diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs
index cfbec8cb27d..9358c20ab95 100644
--- a/tests/ui/option_if_let_else.rs
+++ b/tests/ui/option_if_let_else.rs
@@ -239,6 +239,8 @@ fn main() {
         Ok(a) => a + 1,
     };
     let _ = if let Ok(a) = res { a + 1 } else { 5 };
+    issue10729::reproduce(&None);
+    issue10729::reproduce2(&mut None);
 }
 
 #[allow(dead_code)]
@@ -249,3 +251,25 @@ fn issue9742() -> Option<&'static str> {
         _ => None,
     }
 }
+
+mod issue10729 {
+    #![allow(clippy::unit_arg)]
+
+    pub fn reproduce(initial: &Option<String>) {
+        // 👇 needs `.as_ref()` because initial is an `&Option<_>`
+        match initial {
+            Some(value) => do_something(value),
+            None => {},
+        }
+    }
+
+    pub fn reproduce2(initial: &mut Option<String>) {
+        match initial {
+            Some(value) => do_something2(value),
+            None => {},
+        }
+    }
+
+    fn do_something(_value: &str) {}
+    fn do_something2(_value: &mut str) {}
+}
diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr
index 91d52fc79b8..fde27f21690 100644
--- a/tests/ui/option_if_let_else.stderr
+++ b/tests/ui/option_if_let_else.stderr
@@ -271,5 +271,23 @@ error: use Option::map_or instead of an if let/else
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
-error: aborting due to 21 previous errors
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:260:9
+   |
+LL | /         match initial {
+LL | |             Some(value) => do_something(value),
+LL | |             None => {},
+LL | |         }
+   | |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))`
+
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:267:9
+   |
+LL | /         match initial {
+LL | |             Some(value) => do_something2(value),
+LL | |             None => {},
+LL | |         }
+   | |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))`
+
+error: aborting due to 23 previous errors