Skip to content

Commit 77b21b6

Browse files
Vincent Dal Masoflip1995
authored andcommitted
Move expression check to LateLintPass
Changes: - Move from EarlyLintPass - Fix entrypoint check with function path def_id.
1 parent 4eab691 commit 77b21b6

File tree

10 files changed

+72
-32
lines changed

10 files changed

+72
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ Released 2018-09-13
10001000
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
10011001
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
10021002
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
1003+
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
10031004
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
10041005
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
10051006
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names

clippy_lints/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
474474
reg.register_late_lint_pass(box types::LetUnitValue);
475475
reg.register_late_lint_pass(box types::UnitCmp);
476476
reg.register_late_lint_pass(box loops::Loops);
477-
reg.register_early_lint_pass(box main_recursion::MainRecursion::new());
477+
reg.register_late_lint_pass(box main_recursion::MainRecursion::default());
478478
reg.register_late_lint_pass(box lifetimes::Lifetimes);
479479
reg.register_late_lint_pass(box entry::HashMapPass);
480480
reg.register_late_lint_pass(box ranges::Ranges);
@@ -762,6 +762,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
762762
loops::WHILE_IMMUTABLE_CONDITION,
763763
loops::WHILE_LET_LOOP,
764764
loops::WHILE_LET_ON_ITERATOR,
765+
main_recursion::MAIN_RECURSION,
765766
map_clone::MAP_CLONE,
766767
map_unit_fn::OPTION_MAP_UNIT_FN,
767768
map_unit_fn::RESULT_MAP_UNIT_FN,
@@ -935,6 +936,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
935936
loops::FOR_KV_MAP,
936937
loops::NEEDLESS_RANGE_LOOP,
937938
loops::WHILE_LET_ON_ITERATOR,
939+
main_recursion::MAIN_RECURSION,
938940
map_clone::MAP_CLONE,
939941
matches::MATCH_BOOL,
940942
matches::MATCH_OVERLAPPING_ARM,

clippy_lints/src/main_recursion.rs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,60 @@
1-
2-
use syntax::ast::{Crate, Expr, ExprKind};
3-
use syntax::symbol::sym;
4-
use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
1+
use rustc::hir::{Crate, Expr, ExprKind, QPath};
2+
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
53
use rustc::{declare_tool_lint, impl_lint_pass};
4+
use syntax::symbol::sym;
65

6+
use crate::utils::{is_entrypoint_fn, snippet, span_help_and_lint};
77
use if_chain::if_chain;
8-
use crate::utils::span_help_and_lint;
98

109
declare_clippy_lint! {
10+
/// **What it does:** Checks for recursion using the entrypoint.
11+
///
12+
/// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
13+
/// recursing into main() seems like an unintuitive antipattern we should be able to detect.
14+
///
15+
/// **Known problems:** None.
16+
///
17+
/// **Example:**
18+
/// ```no_run
19+
/// fn main() {
20+
/// main();
21+
/// }
22+
/// ```
1123
pub MAIN_RECURSION,
12-
pedantic,
13-
"function named `foo`, which is not a descriptive name"
24+
style,
25+
"recursion using the entrypoint"
1426
}
1527

28+
#[derive(Default)]
1629
pub struct MainRecursion {
17-
has_no_std_attr: bool
30+
has_no_std_attr: bool,
1831
}
1932

2033
impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
2134

22-
impl MainRecursion {
23-
pub fn new() -> MainRecursion {
24-
MainRecursion {
25-
has_no_std_attr: false
26-
}
27-
}
28-
}
29-
30-
impl EarlyLintPass for MainRecursion {
31-
fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
35+
impl LateLintPass<'_, '_> for MainRecursion {
36+
fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate) {
3237
self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std);
3338
}
3439

35-
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
40+
fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
3641
if self.has_no_std_attr {
3742
return;
3843
}
3944

4045
if_chain! {
4146
if let ExprKind::Call(func, _) = &expr.node;
42-
if let ExprKind::Path(_, path) = &func.node;
43-
if *path == sym::main;
47+
if let ExprKind::Path(path) = &func.node;
48+
if let QPath::Resolved(_, path) = &path;
49+
if let Some(def_id) = path.res.opt_def_id();
50+
if is_entrypoint_fn(cx, def_id);
4451
then {
4552
span_help_and_lint(
4653
cx,
4754
MAIN_RECURSION,
48-
expr.span,
49-
"You are recursing into main()",
50-
"Consider using another function for this recursion"
55+
func.span,
56+
&format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
57+
"consider using another function for this recursion"
5158
)
5259
}
5360
}

src/lintlist/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,13 @@ pub const ALL_LINTS: [Lint; 309] = [
917917
deprecation: None,
918918
module: "booleans",
919919
},
920+
Lint {
921+
name: "main_recursion",
922+
group: "style",
923+
desc: "recursion using the entrypoint",
924+
deprecation: None,
925+
module: "main_recursion",
926+
},
920927
Lint {
921928
name: "manual_memcpy",
922929
group: "perf",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// ignore-macos
2+
// ignore-windows
3+
4+
#![feature(main)]
5+
6+
#[warn(clippy::main_recursion)]
7+
#[allow(unconditional_recursion)]
8+
#[main]
9+
fn a() {
10+
println!("Hello, World!");
11+
a();
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: recursing into entrypoint `a`
2+
--> $DIR/entrypoint_recursion.rs:11:5
3+
|
4+
LL | a();
5+
| ^
6+
|
7+
= note: `-D clippy::main-recursion` implied by `-D warnings`
8+
= help: consider using another function for this recursion
9+
10+
error: aborting due to previous error
11+

tests/ui/crate_level_checks/no_std_main_recursion.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![feature(lang_items, link_args, start, libc)]
2-
#![link_args="-nostartfiles"]
2+
#![link_args = "-nostartfiles"]
33
#![no_std]
44

55
use core::panic::PanicInfo;
@@ -8,7 +8,6 @@ use core::sync::atomic::{AtomicUsize, Ordering};
88
static N: AtomicUsize = AtomicUsize::new(0);
99

1010
#[warn(clippy::main_recursion)]
11-
#[allow(unconditional_recursion)]
1211
#[start]
1312
fn main(argc: isize, argv: *const *const u8) -> isize {
1413
let x = N.load(Ordering::Relaxed);
@@ -28,4 +27,4 @@ fn panic(_info: &PanicInfo) -> ! {
2827
}
2928

3029
#[lang = "eh_personality"]
31-
extern fn eh_personality() {}
30+
extern "C" fn eh_personality() {}

tests/ui/crate_level_checks/no_std_main_recursion.stderr

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#[warn(clippy::main_recursion)]
22
#[allow(unconditional_recursion)]
33
fn main() {
4+
println!("Hello, World!");
45
main();
56
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
error: You are recursing into main()
2-
--> $DIR/std_main_recursion.rs:4:5
1+
error: recursing into entrypoint `main`
2+
--> $DIR/std_main_recursion.rs:5:5
33
|
44
LL | main();
5-
| ^^^^^^
5+
| ^^^^
66
|
77
= note: `-D clippy::main-recursion` implied by `-D warnings`
8-
= help: Consider using another function for this recursion
8+
= help: consider using another function for this recursion
99

1010
error: aborting due to previous error
1111

0 commit comments

Comments
 (0)