generalize let_and_return for any block (closes #340)

This commit is contained in:
Georg Brandl 2015-09-20 13:57:27 +02:00
parent 56b9682624
commit 7cc291d02e
2 changed files with 16 additions and 7 deletions

View file

@ -10,7 +10,7 @@ declare_lint!(pub NEEDLESS_RETURN, Warn,
"using a return statement like `return expr;` where an expression would suffice"); "using a return statement like `return expr;` where an expression would suffice");
declare_lint!(pub LET_AND_RETURN, Warn, declare_lint!(pub LET_AND_RETURN, Warn,
"creating a let-binding and then immediately returning it like `let x = expr; x` at \ "creating a let-binding and then immediately returning it like `let x = expr; x` at \
the end of a function"); the end of a block");
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct ReturnPass; pub struct ReturnPass;
@ -71,11 +71,11 @@ impl ReturnPass {
if_let_chain! { if_let_chain! {
[ [
let Some(stmt) = block.stmts.last(), let Some(stmt) = block.stmts.last(),
let Some(ref retexpr) = block.expr,
let StmtDecl(ref decl, _) = stmt.node, let StmtDecl(ref decl, _) = stmt.node,
let DeclLocal(ref local) = decl.node, let DeclLocal(ref local) = decl.node,
let Some(ref initexpr) = local.init, let Some(ref initexpr) = local.init,
let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node, let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node,
let Some(ref retexpr) = block.expr,
let ExprPath(_, ref path) = retexpr.node, let ExprPath(_, ref path) = retexpr.node,
match_path(path, &[&id.name.as_str()]) match_path(path, &[&id.name.as_str()])
], { ], {
@ -87,7 +87,7 @@ impl ReturnPass {
fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) { fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) {
if in_external_macro(cx, note_span) {return;} if in_external_macro(cx, note_span) {return;}
span_lint(cx, LET_AND_RETURN, lint_span, span_lint(cx, LET_AND_RETURN, lint_span,
"returning the result of a let binding. \ "returning the result of a let binding from a block. \
Consider returning the expression directly."); Consider returning the expression directly.");
if cx.current_level(LET_AND_RETURN) != Level::Allow { if cx.current_level(LET_AND_RETURN) != Level::Allow {
cx.sess().span_note(note_span, cx.sess().span_note(note_span,
@ -106,6 +106,9 @@ impl LateLintPass for ReturnPass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl, fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl,
block: &Block, _: Span, _: NodeId) { block: &Block, _: Span, _: NodeId) {
self.check_block_return(cx, block); self.check_block_return(cx, block);
}
fn check_block(&mut self, cx: &LateContext, block: &Block) {
self.check_let_return(cx, block); self.check_let_return(cx, block);
} }
} }

View file

@ -1,5 +1,6 @@
#![feature(plugin)] #![feature(plugin)]
#![plugin(clippy)] #![plugin(clippy)]
#![allow(unused)]
#![deny(let_and_return)] #![deny(let_and_return)]
@ -9,6 +10,15 @@ fn test() -> i32 {
x //~ERROR returning the result of a let binding x //~ERROR returning the result of a let binding
} }
fn test_inner() -> i32 {
if true {
let x = 5;
x //~ERROR returning the result of a let binding
} else {
0
}
}
fn test_nowarn_1() -> i32 { fn test_nowarn_1() -> i32 {
let mut x = 5; let mut x = 5;
x += 1; x += 1;
@ -27,8 +37,4 @@ fn test_nowarn_3() -> (i32, i32) {
} }
fn main() { fn main() {
test();
test_nowarn_1();
test_nowarn_2();
test_nowarn_3();
} }