about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-05-13 21:45:57 +0200
committerSamuel Tardieu <sam@rfc1149.net>2025-05-23 13:24:04 +0200
commitc364717b15dc7db94ea1f986c2388726b4cc34c3 (patch)
treed1240eea5bbc8a47b13ae3c53ae65bae8fce476e
parent1a864f34a33d0d9d6881c0292887720278c1f942 (diff)
downloadrust-c364717b15dc7db94ea1f986c2388726b4cc34c3.tar.gz
rust-c364717b15dc7db94ea1f986c2388726b4cc34c3.zip
`needless_return`: look inside `else if` parts as well
`if` expressions don't necessarily contain a block in the `else` part in
the presence of an `else if`. The `else` part, if present, must be
handled as a regular expression, not necessarily as a block expression.
-rw-r--r--clippy_lints/src/panic_unimplemented.rs1
-rw-r--r--clippy_lints/src/returns.rs4
-rw-r--r--tests/ui/needless_return.fixed65
-rw-r--r--tests/ui/needless_return.rs65
-rw-r--r--tests/ui/needless_return.stderr98
5 files changed, 230 insertions, 3 deletions
diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs
index 8962f36db1e..449d3da7639 100644
--- a/clippy_lints/src/panic_unimplemented.rs
+++ b/clippy_lints/src/panic_unimplemented.rs
@@ -152,7 +152,6 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
                 expr.span,
                 "`panic_any` should not be present in production code",
             );
-            return;
         }
     }
 }
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 122d97fdf81..7326d96985c 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -428,7 +428,9 @@ fn check_final_expr<'tcx>(
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
             if let Some(else_clause) = else_clause_opt {
-                check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
+                // The `RetReplacement` won't be used there as `else_clause` will be either a block or
+                // a `if` expression.
+                check_final_expr(cx, else_clause, semi_spans, RetReplacement::Empty, match_ty_opt);
             }
         },
         // a match expr, check all arms
diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed
index ad625ad6d50..9b90171f5fb 100644
--- a/tests/ui/needless_return.fixed
+++ b/tests/ui/needless_return.fixed
@@ -452,3 +452,68 @@ pub unsafe fn issue_12157() -> *const i32 {
     (unsafe { todo() } as *const i32)
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        //~^ needless_return
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            1
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            3
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            1
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs
index 41d7e5bdd50..fc4590c9cba 100644
--- a/tests/ui/needless_return.rs
+++ b/tests/ui/needless_return.rs
@@ -461,3 +461,68 @@ pub unsafe fn issue_12157() -> *const i32 {
     return unsafe { todo() } as *const i32;
     //~^ needless_return
 }
+
+mod else_ifs {
+    fn test1(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            return 2;
+        //~^ needless_return
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test2(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    fn test3(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+        //~^ needless_return
+        } else if a < 10 {
+            2
+        } else {
+            return 3;
+            //~^ needless_return
+        }
+    }
+
+    #[allow(clippy::match_single_binding, clippy::redundant_pattern)]
+    fn test4(a: i32) -> u32 {
+        if a == 0 {
+            return 1;
+            //~^ needless_return
+        } else if if if a > 0x1_1 {
+            return 2;
+        } else {
+            return 5;
+        } {
+            true
+        } else {
+            true
+        } {
+            0xDEADC0DE
+        } else if match a {
+            b @ _ => {
+                return 1;
+            },
+        } {
+            0xDEADBEEF
+        } else {
+            1
+        }
+    }
+}
diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr
index 80863b9b62b..212d662c967 100644
--- a/tests/ui/needless_return.stderr
+++ b/tests/ui/needless_return.stderr
@@ -703,5 +703,101 @@ LL -     return unsafe { todo() } as *const i32;
 LL +     (unsafe { todo() } as *const i32)
    |
 
-error: aborting due to 55 previous errors
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:468:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:471:13
+   |
+LL |             return 2;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 2;
+LL +             2
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:474:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:481:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:486:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:493:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:498:13
+   |
+LL |             return 3;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 3;
+LL +             3
+   |
+
+error: unneeded `return` statement
+  --> tests/ui/needless_return.rs:506:13
+   |
+LL |             return 1;
+   |             ^^^^^^^^
+   |
+help: remove `return`
+   |
+LL -             return 1;
+LL +             1
+   |
+
+error: aborting due to 63 previous errors