Skip to content

Commit 4eab691

Browse files
Vincent Dal Masoflip1995
authored andcommitted
Add recursion check on main function
Changes: - Add MainRecursion lint to clippy - Check for no-std setup fixes #333
1 parent ca6a9be commit 4eab691

File tree

6 files changed

+104
-0
lines changed

6 files changed

+104
-0
lines changed

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ pub mod let_if_seq;
208208
pub mod lifetimes;
209209
pub mod literal_representation;
210210
pub mod loops;
211+
pub mod main_recursion;
211212
pub mod map_clone;
212213
pub mod map_unit_fn;
213214
pub mod matches;
@@ -473,6 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
473474
reg.register_late_lint_pass(box types::LetUnitValue);
474475
reg.register_late_lint_pass(box types::UnitCmp);
475476
reg.register_late_lint_pass(box loops::Loops);
477+
reg.register_early_lint_pass(box main_recursion::MainRecursion::new());
476478
reg.register_late_lint_pass(box lifetimes::Lifetimes);
477479
reg.register_late_lint_pass(box entry::HashMapPass);
478480
reg.register_late_lint_pass(box ranges::Ranges);

clippy_lints/src/main_recursion.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
use syntax::ast::{Crate, Expr, ExprKind};
3+
use syntax::symbol::sym;
4+
use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
5+
use rustc::{declare_tool_lint, impl_lint_pass};
6+
7+
use if_chain::if_chain;
8+
use crate::utils::span_help_and_lint;
9+
10+
declare_clippy_lint! {
11+
pub MAIN_RECURSION,
12+
pedantic,
13+
"function named `foo`, which is not a descriptive name"
14+
}
15+
16+
pub struct MainRecursion {
17+
has_no_std_attr: bool
18+
}
19+
20+
impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
21+
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) {
32+
self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std);
33+
}
34+
35+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
36+
if self.has_no_std_attr {
37+
return;
38+
}
39+
40+
if_chain! {
41+
if let ExprKind::Call(func, _) = &expr.node;
42+
if let ExprKind::Path(_, path) = &func.node;
43+
if *path == sym::main;
44+
then {
45+
span_help_and_lint(
46+
cx,
47+
MAIN_RECURSION,
48+
expr.span,
49+
"You are recursing into main()",
50+
"Consider using another function for this recursion"
51+
)
52+
}
53+
}
54+
}
55+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![feature(lang_items, link_args, start, libc)]
2+
#![link_args="-nostartfiles"]
3+
#![no_std]
4+
5+
use core::panic::PanicInfo;
6+
use core::sync::atomic::{AtomicUsize, Ordering};
7+
8+
static N: AtomicUsize = AtomicUsize::new(0);
9+
10+
#[warn(clippy::main_recursion)]
11+
#[allow(unconditional_recursion)]
12+
#[start]
13+
fn main(argc: isize, argv: *const *const u8) -> isize {
14+
let x = N.load(Ordering::Relaxed);
15+
N.store(x + 1, Ordering::Relaxed);
16+
17+
if x < 3 {
18+
main(argc, argv);
19+
}
20+
21+
0
22+
}
23+
24+
#[allow(clippy::empty_loop)]
25+
#[panic_handler]
26+
fn panic(_info: &PanicInfo) -> ! {
27+
loop {}
28+
}
29+
30+
#[lang = "eh_personality"]
31+
extern fn eh_personality() {}

tests/ui/crate_level_checks/no_std_main_recursion.stderr

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[warn(clippy::main_recursion)]
2+
#[allow(unconditional_recursion)]
3+
fn main() {
4+
main();
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: You are recursing into main()
2+
--> $DIR/std_main_recursion.rs:4:5
3+
|
4+
LL | main();
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+

0 commit comments

Comments
 (0)