about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-01-20 11:47:19 +0100
committerSamuel Tardieu <sam@rfc1149.net>2025-01-20 11:53:08 +0100
commitf0b99b2b388ebfd3b5b2604737d2b39db64f9081 (patch)
tree1e4289f182cf55b029509ca7ba59b02b621b8cf7
parent2280b8a09967891b6c3d2d53a001c514954489c3 (diff)
downloadrust-f0b99b2b388ebfd3b5b2604737d2b39db64f9081.tar.gz
rust-f0b99b2b388ebfd3b5b2604737d2b39db64f9081.zip
`needless_option_take`: add autofix
-rw-r--r--clippy_lints/src/methods/needless_option_take.rs18
-rw-r--r--tests/ui/needless_option_take.fixed58
-rw-r--r--tests/ui/needless_option_take.stderr36
3 files changed, 99 insertions, 13 deletions
diff --git a/clippy_lints/src/methods/needless_option_take.rs b/clippy_lints/src/methods/needless_option_take.rs
index c41ce2481d7..88b9c69f6f9 100644
--- a/clippy_lints/src/methods/needless_option_take.rs
+++ b/clippy_lints/src/methods/needless_option_take.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -10,13 +11,22 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
     // Checks if expression type is equal to sym::Option and if the expr is not a syntactic place
     if !recv.is_syntactic_place_expr() && is_expr_option(cx, recv) {
         if let Some(function_name) = source_of_temporary_value(recv) {
-            span_lint_and_note(
+            span_lint_and_then(
                 cx,
                 NEEDLESS_OPTION_TAKE,
                 expr.span,
                 "called `Option::take()` on a temporary value",
-                None,
-                format!("`{function_name}` creates a temporary value, so calling take() has no effect"),
+                |diag| {
+                    diag.note(format!(
+                        "`{function_name}` creates a temporary value, so calling take() has no effect"
+                    ));
+                    diag.span_suggestion(
+                        expr.span.with_lo(recv.span.hi()),
+                        "remove",
+                        "",
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         }
     }
diff --git a/tests/ui/needless_option_take.fixed b/tests/ui/needless_option_take.fixed
new file mode 100644
index 00000000000..6514b67ef7a
--- /dev/null
+++ b/tests/ui/needless_option_take.fixed
@@ -0,0 +1,58 @@
+struct MyStruct;
+
+impl MyStruct {
+    pub fn get_option() -> Option<Self> {
+        todo!()
+    }
+}
+
+fn return_option() -> Option<i32> {
+    todo!()
+}
+
+fn main() {
+    println!("Testing non erroneous option_take_on_temporary");
+    let mut option = Some(1);
+    let _ = Box::new(move || option.take().unwrap());
+
+    println!("Testing non erroneous option_take_on_temporary");
+    let x = Some(3);
+    x.as_ref();
+
+    let x = Some(3);
+    x.as_ref();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    println!("Testing non erroneous option_take_on_temporary");
+    let mut x = Some(3);
+    let y = x.as_mut();
+
+    let mut x = Some(3);
+    let y = x.as_mut();
+    //~^ ERROR: called `Option::take()` on a temporary value
+    let y = x.replace(289);
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = Some(3).as_mut();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = Option::as_mut(&mut x);
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let x = return_option();
+    let x = return_option();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let x = MyStruct::get_option();
+    let x = MyStruct::get_option();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let mut my_vec = vec![1, 2, 3];
+    my_vec.push(4);
+    let y = my_vec.first();
+    let y = my_vec.first();
+    //~^ ERROR: called `Option::take()` on a temporary value
+
+    let y = my_vec.first();
+    //~^ ERROR: called `Option::take()` on a temporary value
+}
diff --git a/tests/ui/needless_option_take.stderr b/tests/ui/needless_option_take.stderr
index e036bd53170..3fc339ed79e 100644
--- a/tests/ui/needless_option_take.stderr
+++ b/tests/ui/needless_option_take.stderr
@@ -2,7 +2,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:23:5
    |
 LL |     x.as_ref().take();
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^-------
+   |               |
+   |               help: remove
    |
    = note: `as_ref` creates a temporary value, so calling take() has no effect
    = note: `-D clippy::needless-option-take` implied by `-D warnings`
@@ -12,7 +14,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:31:13
    |
 LL |     let y = x.as_mut().take();
-   |             ^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^-------
+   |                       |
+   |                       help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -20,7 +24,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:33:13
    |
 LL |     let y = x.replace(289).take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `replace` creates a temporary value, so calling take() has no effect
 
@@ -28,7 +34,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:36:13
    |
 LL |     let y = Some(3).as_mut().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^-------
+   |                             |
+   |                             help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -36,7 +44,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:39:13
    |
 LL |     let y = Option::as_mut(&mut x).take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^-------
+   |                                   |
+   |                                   help: remove
    |
    = note: `as_mut` creates a temporary value, so calling take() has no effect
 
@@ -44,7 +54,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:43:13
    |
 LL |     let x = return_option().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^-------
+   |                            |
+   |                            help: remove
    |
    = note: `return_option` creates a temporary value, so calling take() has no effect
 
@@ -52,7 +64,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:47:13
    |
 LL |     let x = MyStruct::get_option().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^^^^^-------
+   |                                   |
+   |                                   help: remove
    |
    = note: `get_option` creates a temporary value, so calling take() has no effect
 
@@ -60,7 +74,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:53:13
    |
 LL |     let y = my_vec.first().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `first` creates a temporary value, so calling take() has no effect
 
@@ -68,7 +84,9 @@ error: called `Option::take()` on a temporary value
   --> tests/ui/needless_option_take.rs:56:13
    |
 LL |     let y = my_vec.first().take();
-   |             ^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^-------
+   |                           |
+   |                           help: remove
    |
    = note: `first` creates a temporary value, so calling take() has no effect