3427: Fix wrong suggestion for `redundant_closure_call` r=oli-obk a=mikerite

Fixes #1684

Co-authored-by: Michael Wright <mikerite@lavabit.com>
This commit is contained in:
bors[bot] 2018-11-14 08:57:32 +00:00
commit 973e70cef7
2 changed files with 50 additions and 16 deletions

View File

@ -15,7 +15,7 @@ use if_chain::if_chain;
use std::char; use std::char;
use crate::syntax::ast::*; use crate::syntax::ast::*;
use crate::syntax::source_map::Span; use crate::syntax::source_map::Span;
use crate::syntax::visit::FnKind; use crate::syntax::visit::{FnKind, Visitor, walk_expr};
use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then}; use crate::utils::{constants, snippet, snippet_opt, span_help_and_lint, span_lint, span_lint_and_then};
use crate::rustc_errors::Applicability; use crate::rustc_errors::Applicability;
@ -199,6 +199,31 @@ impl LintPass for MiscEarly {
} }
} }
// Used to find `return` statements or equivalents e.g. `?`
struct ReturnVisitor {
found_return: bool,
}
impl ReturnVisitor {
fn new() -> Self {
Self {
found_return: false,
}
}
}
impl<'ast> Visitor<'ast> for ReturnVisitor {
fn visit_expr(&mut self, ex: &'ast Expr) {
if let ExprKind::Ret(_) = ex.node {
self.found_return = true;
} else if let ExprKind::Try(_) = ex.node {
self.found_return = true;
}
walk_expr(self, ex)
}
}
impl EarlyLintPass for MiscEarly { impl EarlyLintPass for MiscEarly {
fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) {
for param in &gen.params { for param in &gen.params {
@ -311,21 +336,25 @@ impl EarlyLintPass for MiscEarly {
match expr.node { match expr.node {
ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node { ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node {
if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node { if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node {
span_lint_and_then( let mut visitor = ReturnVisitor::new();
cx, visitor.visit_expr(block);
REDUNDANT_CLOSURE_CALL, if !visitor.found_return {
expr.span, span_lint_and_then(
"Try not to call a closure in the expression where it is declared.", cx,
|db| if decl.inputs.is_empty() { REDUNDANT_CLOSURE_CALL,
let hint = snippet(cx, block.span, "..").into_owned(); expr.span,
db.span_suggestion_with_applicability( "Try not to call a closure in the expression where it is declared.",
expr.span, |db| if decl.inputs.is_empty() {
"Try doing something like: ", let hint = snippet(cx, block.span, "..").into_owned();
hint, db.span_suggestion_with_applicability(
Applicability::MachineApplicable, // snippet expr.span,
); "Try doing something like: ",
}, hint,
); Applicability::MachineApplicable, // snippet
);
},
);
}
} }
}, },
ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node { ExprKind::Unary(UnOp::Neg, ref inner) => if let ExprKind::Unary(UnOp::Neg, _) = inner.node {

View File

@ -28,4 +28,9 @@ fn main() {
i = closure(3); i = closure(3);
i = closure(4); i = closure(4);
#[allow(clippy::needless_return)]
(|| return 2)();
(|| -> Option<i32> { None? })();
(|| -> Result<i32, i32> { r#try!(Err(2)) })();
} }