about summary refs log tree commit diff
diff options
context:
space:
mode:
authorapoisternex <santinoferrazzuolo@proton.me>2024-08-03 21:24:51 -0300
committerapoisternex <santinoferrazzuolo@proton.me>2024-08-03 21:24:51 -0300
commitaf35dcd33012c131bf2d3675bb40591b740c7728 (patch)
treef4bd8e38ffec114e63242edcf0e25f142ce16bdd
parent377d72ae8b74d31301f40cbe0bd110bf1e01ccec (diff)
downloadrust-af35dcd33012c131bf2d3675bb40591b740c7728.tar.gz
rust-af35dcd33012c131bf2d3675bb40591b740c7728.zip
Fix [`needless_return`] false negative when returned expression borrows a value
Fixes #12907

changelog: Fix [`needless_return`] false negative when returned expression borrows a value
-rw-r--r--clippy_lints/src/returns.rs22
-rw-r--r--tests/ui/needless_return.fixed4
-rw-r--r--tests/ui/needless_return.rs4
-rw-r--r--tests/ui/needless_return.stderr14
4 files changed, 39 insertions, 5 deletions
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 13016cdadb0..034c44a971d 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{for_each_expr, for_each_unconsumed_temporary, Descend};
 use clippy_utils::{
     binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res,
     path_to_local_id, span_contains_cfg, span_find_starting_semi,
@@ -384,10 +384,24 @@ fn check_final_expr<'tcx>(
                 }
             };
 
-            let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
-            if borrows {
-                return;
+            if let Some(inner) = inner {
+                if for_each_unconsumed_temporary(cx, inner, |temporary_ty| {
+                    if temporary_ty.has_significant_drop(cx.tcx, cx.param_env)
+                        && temporary_ty
+                            .walk()
+                            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static()))
+                    {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(())
+                    }
+                })
+                .is_break()
+                {
+                    return;
+                }
             }
+
             if ret_span.from_expansion() {
                 return;
             }
diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed
index fc4129e1db8..c5c570690b4 100644
--- a/tests/ui/needless_return.fixed
+++ b/tests/ui/needless_return.fixed
@@ -355,4 +355,8 @@ fn conjunctive_blocks() -> String {
     ({ "a".to_string() } + "b" + { "c" })
 }
 
+fn issue12907() -> String {
+    "".split("").next().unwrap().to_string()
+}
+
 fn main() {}
diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs
index 61c7a02008f..738611391df 100644
--- a/tests/ui/needless_return.rs
+++ b/tests/ui/needless_return.rs
@@ -365,4 +365,8 @@ fn conjunctive_blocks() -> String {
     return { "a".to_string() } + "b" + { "c" };
 }
 
+fn issue12907() -> String {
+    return "".split("").next().unwrap().to_string();
+}
+
 fn main() {}
diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr
index ea9c230eafd..da0fa220d8c 100644
--- a/tests/ui/needless_return.stderr
+++ b/tests/ui/needless_return.stderr
@@ -665,5 +665,17 @@ LL -     return { "a".to_string() } + "b" + { "c" };
 LL +     ({ "a".to_string() } + "b" + { "c" })
    |
 
-error: aborting due to 53 previous errors
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:369:5
+   |
+LL |     return "".split("").next().unwrap().to_string();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -     return "".split("").next().unwrap().to_string();
+LL +     "".split("").next().unwrap().to_string()
+   |
+
+error: aborting due to 54 previous errors