mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Added FORCED_RETURN
lint.
This commit is contained in:
parent
3f24cdf10f
commit
d5d6692288
5 changed files with 211 additions and 1 deletions
|
@ -7,7 +7,7 @@
|
|||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 289 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 290 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
|
106
clippy_lints/src/forced_return.rs
Normal file
106
clippy_lints/src/forced_return.rs
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
|
||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::{ast::NodeId, source_map::Span};
|
||||
use crate::utils::{snippet_opt, span_lint_and_then};
|
||||
|
||||
/// **What it does:** Checks for missing return statements at the end of a block.
|
||||
///
|
||||
/// **Why is this bad?** Actually it is idiomatic Rust code. Programmers coming
|
||||
/// from other languages might prefer the expressiveness of `return`.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// fn foo(x: usize) {
|
||||
/// x
|
||||
/// }
|
||||
/// ```
|
||||
/// add return
|
||||
/// ```rust
|
||||
/// fn foo(x: usize) {
|
||||
/// return x;
|
||||
/// }
|
||||
/// ```
|
||||
declare_clippy_lint! {
|
||||
pub FORCED_RETURN,
|
||||
restriction,
|
||||
"use a return statement like `return expr` instead of an expression"
|
||||
}
|
||||
|
||||
pub struct ForcedReturnPass;
|
||||
|
||||
impl ForcedReturnPass {
|
||||
fn show_suggestion(cx: &LateContext<'_, '_>, span: syntax_pos::Span) {
|
||||
span_lint_and_then(cx, FORCED_RETURN, span, "missing return statement", |db| {
|
||||
if let Some(snippet) = snippet_opt(cx, span) {
|
||||
db.span_suggestion_with_applicability(
|
||||
span,
|
||||
"add `return` as shown",
|
||||
format!("return {}", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn expr_match(cx: &LateContext<'_, '_>, kind: &ExprKind) {
|
||||
match kind {
|
||||
ExprKind::Block(ref block, ..) => {
|
||||
if let Some(ref expr) = block.expr {
|
||||
Self::expr_match(cx, &expr.node);
|
||||
}
|
||||
},
|
||||
ExprKind::If(.., if_expr, else_expr) => {
|
||||
Self::expr_match(cx, &if_expr.node);
|
||||
|
||||
if let Some(else_expr) = else_expr {
|
||||
Self::expr_match(cx, &else_expr.node);
|
||||
}
|
||||
},
|
||||
ExprKind::Match(_, arms, ..) => {
|
||||
for arm in arms {
|
||||
Self::expr_match(cx, &arm.body.node);
|
||||
}
|
||||
},
|
||||
ExprKind::Lit(lit) => Self::show_suggestion(cx, lit.span),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LintPass for ForcedReturnPass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(FORCED_RETURN)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ForcedReturnPass {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
_: FnKind<'tcx>,
|
||||
_: &'tcx FnDecl,
|
||||
body: &'tcx Body,
|
||||
_: Span,
|
||||
_: NodeId,
|
||||
) {
|
||||
let def_id = cx.tcx.hir.body_owner_def_id(body.id());
|
||||
let mir = cx.tcx.optimized_mir(def_id);
|
||||
|
||||
if !mir.return_ty().is_unit() {
|
||||
Self::expr_match(cx, &body.value.node);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -185,6 +185,7 @@ pub mod reference;
|
|||
pub mod regex;
|
||||
pub mod replace_consts;
|
||||
pub mod returns;
|
||||
pub mod forced_return;
|
||||
pub mod serde_api;
|
||||
pub mod shadow;
|
||||
pub mod slow_vector_initialization;
|
||||
|
@ -371,6 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
|||
reg.register_late_lint_pass(box unicode::Unicode);
|
||||
reg.register_late_lint_pass(box strings::StringAdd);
|
||||
reg.register_early_lint_pass(box returns::ReturnPass);
|
||||
reg.register_late_lint_pass(box forced_return::ForcedReturnPass);
|
||||
reg.register_late_lint_pass(box methods::Pass);
|
||||
reg.register_late_lint_pass(box map_clone::Pass);
|
||||
reg.register_late_lint_pass(box shadow::Pass);
|
||||
|
@ -502,6 +504,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
|||
strings::STRING_ADD,
|
||||
write::PRINT_STDOUT,
|
||||
write::USE_DEBUG,
|
||||
forced_return::FORCED_RETURN,
|
||||
]);
|
||||
|
||||
reg.register_lint_group("clippy::pedantic", Some("clippy_pedantic"), vec![
|
||||
|
|
55
tests/ui/forced_return.rs
Normal file
55
tests/ui/forced_return.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#![warn(clippy::forced_return)]
|
||||
|
||||
fn test_end_of_fn() -> bool {
|
||||
if true {
|
||||
// no error!
|
||||
return true;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_bool)]
|
||||
fn test_if_block() -> bool {
|
||||
if true {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::match_bool)]
|
||||
fn test_match(x: bool) -> bool {
|
||||
match x {
|
||||
true => false,
|
||||
false => {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_closure() {
|
||||
let _ = || {
|
||||
true
|
||||
};
|
||||
let _ = || true;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = test_end_of_fn();
|
||||
let _ = test_if_block();
|
||||
let _ = test_match(true);
|
||||
test_closure();
|
||||
}
|
46
tests/ui/forced_return.stderr
Normal file
46
tests/ui/forced_return.stderr
Normal file
|
@ -0,0 +1,46 @@
|
|||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:21:5
|
||||
|
|
||||
21 | true
|
||||
| ^^^^ help: add `return` as shown: `return true`
|
||||
|
|
||||
= note: `-D clippy::forced-return` implied by `-D warnings`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:27:9
|
||||
|
|
||||
27 | true
|
||||
| ^^^^ help: add `return` as shown: `return true`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:29:9
|
||||
|
|
||||
29 | false
|
||||
| ^^^^^ help: add `return` as shown: `return false`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:36:17
|
||||
|
|
||||
36 | true => false,
|
||||
| ^^^^^ help: add `return` as shown: `return false`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:38:13
|
||||
|
|
||||
38 | true
|
||||
| ^^^^ help: add `return` as shown: `return true`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:45:9
|
||||
|
|
||||
45 | true
|
||||
| ^^^^ help: add `return` as shown: `return true`
|
||||
|
||||
error: missing return statement
|
||||
--> $DIR/forced_return.rs:47:16
|
||||
|
|
||||
47 | let _ = || true;
|
||||
| ^^^^ help: add `return` as shown: `return true`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
Loading…
Reference in a new issue