Skip to content

Commit aed2b98

Browse files
committed
Renamed to implicit_return.
Covered all other kinds besides `ExprKind::Lit`. Added check for replacing `break` with `return`.
1 parent 19db2f1 commit aed2b98

File tree

6 files changed

+154
-121
lines changed

6 files changed

+154
-121
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ All notable changes to this project will be documented in this file.
706706
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
707707
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
708708
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
709+
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
709710
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
710711
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
711712
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
@@ -756,7 +757,6 @@ All notable changes to this project will be documented in this file.
756757
[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
757758
[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
758759
[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
759-
[`missing_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_returns
760760
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
761761
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
762762
[`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception

clippy_lints/src/implicit_return.rs

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution.
3+
//
4+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7+
// option. This file may not be copied, modified, or distributed
8+
// except according to those terms.
9+
10+
use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
11+
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
12+
use crate::rustc::{declare_tool_lint, lint_array};
13+
use crate::rustc_errors::Applicability;
14+
use crate::syntax::{ast::NodeId, source_map::Span};
15+
use crate::utils::{snippet_opt, span_lint_and_then};
16+
17+
/// **What it does:** Checks for missing return statements at the end of a block.
18+
///
19+
/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
20+
/// coming from other languages might prefer the expressiveness of `return`.
21+
///
22+
/// **Known problems:** None.
23+
///
24+
/// **Example:**
25+
/// ```rust
26+
/// fn foo(x: usize) {
27+
/// x
28+
/// }
29+
/// ```
30+
/// add return
31+
/// ```rust
32+
/// fn foo(x: usize) {
33+
/// return x;
34+
/// }
35+
/// ```
36+
declare_clippy_lint! {
37+
pub IMPLICIT_RETURN,
38+
restriction,
39+
"use a return statement like `return expr` instead of an expression"
40+
}
41+
42+
pub struct Pass;
43+
44+
impl Pass {
45+
fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
46+
match &expr.node {
47+
ExprKind::Block(block, ..) => {
48+
if let Some(expr) = &block.expr {
49+
Self::expr_match(cx, expr);
50+
}
51+
// only needed in the case of `break` with `;` at the end
52+
else if let Some(stmt) = block.stmts.last() {
53+
if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
54+
Self::expr_match(cx, expr);
55+
}
56+
}
57+
},
58+
// use `return` instead of `break`
59+
ExprKind::Break(.., break_expr) => {
60+
if let Some(break_expr) = break_expr {
61+
span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
62+
if let Some(snippet) = snippet_opt(cx, break_expr.span) {
63+
db.span_suggestion_with_applicability(
64+
expr.span,
65+
"change `break` to `return` as shown",
66+
format!("return {}", snippet),
67+
Applicability::MachineApplicable,
68+
);
69+
}
70+
});
71+
}
72+
},
73+
ExprKind::If(.., if_expr, else_expr) => {
74+
Self::expr_match(cx, if_expr);
75+
76+
if let Some(else_expr) = else_expr {
77+
Self::expr_match(cx, else_expr);
78+
}
79+
},
80+
ExprKind::Match(_, arms, ..) => {
81+
for arm in arms {
82+
Self::expr_match(cx, &arm.body);
83+
}
84+
},
85+
// loops could be using `break` instead of `return`
86+
ExprKind::Loop(block, ..) => {
87+
if let Some(expr) = &block.expr {
88+
Self::expr_match(cx, expr);
89+
}
90+
},
91+
// skip if it already has a return statement
92+
ExprKind::Ret(..) => (),
93+
// everything else is missing `return`
94+
_ => span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
95+
if let Some(snippet) = snippet_opt(cx, expr.span) {
96+
db.span_suggestion_with_applicability(
97+
expr.span,
98+
"add `return` as shown",
99+
format!("return {}", snippet),
100+
Applicability::MachineApplicable,
101+
);
102+
}
103+
}),
104+
}
105+
}
106+
}
107+
108+
impl LintPass for Pass {
109+
fn get_lints(&self) -> LintArray {
110+
lint_array!(IMPLICIT_RETURN)
111+
}
112+
}
113+
114+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
115+
fn check_fn(
116+
&mut self,
117+
cx: &LateContext<'a, 'tcx>,
118+
_: FnKind<'tcx>,
119+
_: &'tcx FnDecl,
120+
body: &'tcx Body,
121+
_: Span,
122+
_: NodeId,
123+
) {
124+
let def_id = cx.tcx.hir.body_owner_def_id(body.id());
125+
let mir = cx.tcx.optimized_mir(def_id);
126+
127+
if !mir.return_ty().is_unit() {
128+
Self::expr_match(cx, &body.value);
129+
}
130+
}
131+
}

clippy_lints/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ pub mod functions;
126126
pub mod identity_conversion;
127127
pub mod identity_op;
128128
pub mod if_not_else;
129+
pub mod implicit_return;
129130
pub mod indexing_slicing;
130131
pub mod infallible_destructuring_match;
131132
pub mod infinite_iter;
@@ -152,7 +153,6 @@ pub mod misc;
152153
pub mod misc_early;
153154
pub mod missing_doc;
154155
pub mod missing_inline;
155-
pub mod missing_returns;
156156
pub mod multiple_crate_versions;
157157
pub mod mut_mut;
158158
pub mod mut_reference;
@@ -372,7 +372,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
372372
reg.register_late_lint_pass(box unicode::Unicode);
373373
reg.register_late_lint_pass(box strings::StringAdd);
374374
reg.register_early_lint_pass(box returns::ReturnPass);
375-
reg.register_late_lint_pass(box missing_returns::Pass);
375+
reg.register_late_lint_pass(box implicit_return::Pass);
376376
reg.register_late_lint_pass(box methods::Pass);
377377
reg.register_late_lint_pass(box map_clone::Pass);
378378
reg.register_late_lint_pass(box shadow::Pass);
@@ -487,6 +487,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
487487
arithmetic::FLOAT_ARITHMETIC,
488488
arithmetic::INTEGER_ARITHMETIC,
489489
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
490+
implicit_return::IMPLICIT_RETURN,
490491
indexing_slicing::INDEXING_SLICING,
491492
inherent_impl::MULTIPLE_INHERENT_IMPL,
492493
literal_representation::DECIMAL_LITERAL_REPRESENTATION,
@@ -498,7 +499,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
498499
misc::FLOAT_CMP_CONST,
499500
missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
500501
missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
501-
missing_returns::MISSING_RETURNS,
502502
panic_unimplemented::UNIMPLEMENTED,
503503
shadow::SHADOW_REUSE,
504504
shadow::SHADOW_SAME,

clippy_lints/src/missing_returns.rs

-106
This file was deleted.

tests/ui/missing_returns.rs renamed to tests/ui/implicit_return.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313

14-
#![warn(clippy::missing_returns)]
14+
#![warn(clippy::implicit_return)]
1515

1616
fn test_end_of_fn() -> bool {
1717
if true {
@@ -40,6 +40,13 @@ fn test_match(x: bool) -> bool {
4040
}
4141
}
4242

43+
#[allow(clippy::never_loop)]
44+
fn test_loop() -> bool {
45+
loop {
46+
break true;
47+
}
48+
}
49+
4350
fn test_closure() {
4451
let _ = || {
4552
true
@@ -51,5 +58,6 @@ fn main() {
5158
let _ = test_end_of_fn();
5259
let _ = test_if_block();
5360
let _ = test_match(true);
61+
let _ = test_loop();
5462
test_closure();
5563
}

tests/ui/missing_returns.stderr renamed to tests/ui/implicit_return.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,45 @@
11
error: missing return statement
2-
--> $DIR/missing_returns.rs:21:5
2+
--> $DIR/implicit_return.rs:21:5
33
|
44
21 | true
55
| ^^^^ help: add `return` as shown: `return true`
66
|
7-
= note: `-D clippy::missing-returns` implied by `-D warnings`
7+
= note: `-D clippy::implicit-return` implied by `-D warnings`
88

99
error: missing return statement
10-
--> $DIR/missing_returns.rs:27:9
10+
--> $DIR/implicit_return.rs:27:9
1111
|
1212
27 | true
1313
| ^^^^ help: add `return` as shown: `return true`
1414

1515
error: missing return statement
16-
--> $DIR/missing_returns.rs:29:9
16+
--> $DIR/implicit_return.rs:29:9
1717
|
1818
29 | false
1919
| ^^^^^ help: add `return` as shown: `return false`
2020

2121
error: missing return statement
22-
--> $DIR/missing_returns.rs:36:17
22+
--> $DIR/implicit_return.rs:36:17
2323
|
2424
36 | true => false,
2525
| ^^^^^ help: add `return` as shown: `return false`
2626

2727
error: missing return statement
28-
--> $DIR/missing_returns.rs:38:13
28+
--> $DIR/implicit_return.rs:38:13
2929
|
3030
38 | true
3131
| ^^^^ help: add `return` as shown: `return true`
3232

3333
error: missing return statement
34-
--> $DIR/missing_returns.rs:45:9
34+
--> $DIR/implicit_return.rs:52:9
3535
|
36-
45 | true
36+
52 | true
3737
| ^^^^ help: add `return` as shown: `return true`
3838

3939
error: missing return statement
40-
--> $DIR/missing_returns.rs:47:16
40+
--> $DIR/implicit_return.rs:54:16
4141
|
42-
47 | let _ = || true;
42+
54 | let _ = || true;
4343
| ^^^^ help: add `return` as shown: `return true`
4444

4545
error: aborting due to 7 previous errors

0 commit comments

Comments
 (0)