mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #4203 - Urriel:feat/333_calling_main, r=flip1995
Add recursion check on main function Changes: - Add MainRecursion lint to Clippy - Check for no-std setup fixes #333 changelog: Add `main_recursion` lint
This commit is contained in:
commit
a813c057d5
@ -1000,6 +1000,7 @@ Released 2018-09-13
|
||||
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
|
||||
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
|
||||
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
|
||||
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
|
||||
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
|
||||
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
|
||||
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 309 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 310 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:
|
||||
|
||||
|
@ -208,6 +208,7 @@ pub mod let_if_seq;
|
||||
pub mod lifetimes;
|
||||
pub mod literal_representation;
|
||||
pub mod loops;
|
||||
pub mod main_recursion;
|
||||
pub mod map_clone;
|
||||
pub mod map_unit_fn;
|
||||
pub mod matches;
|
||||
@ -473,6 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||
reg.register_late_lint_pass(box types::LetUnitValue);
|
||||
reg.register_late_lint_pass(box types::UnitCmp);
|
||||
reg.register_late_lint_pass(box loops::Loops);
|
||||
reg.register_late_lint_pass(box main_recursion::MainRecursion::default());
|
||||
reg.register_late_lint_pass(box lifetimes::Lifetimes);
|
||||
reg.register_late_lint_pass(box entry::HashMapPass);
|
||||
reg.register_late_lint_pass(box ranges::Ranges);
|
||||
@ -760,6 +762,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||
loops::WHILE_IMMUTABLE_CONDITION,
|
||||
loops::WHILE_LET_LOOP,
|
||||
loops::WHILE_LET_ON_ITERATOR,
|
||||
main_recursion::MAIN_RECURSION,
|
||||
map_clone::MAP_CLONE,
|
||||
map_unit_fn::OPTION_MAP_UNIT_FN,
|
||||
map_unit_fn::RESULT_MAP_UNIT_FN,
|
||||
@ -933,6 +936,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
|
||||
loops::FOR_KV_MAP,
|
||||
loops::NEEDLESS_RANGE_LOOP,
|
||||
loops::WHILE_LET_ON_ITERATOR,
|
||||
main_recursion::MAIN_RECURSION,
|
||||
map_clone::MAP_CLONE,
|
||||
matches::MATCH_BOOL,
|
||||
matches::MATCH_OVERLAPPING_ARM,
|
||||
|
62
clippy_lints/src/main_recursion.rs
Normal file
62
clippy_lints/src/main_recursion.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use rustc::hir::{Crate, Expr, ExprKind, QPath};
|
||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_tool_lint, impl_lint_pass};
|
||||
use syntax::symbol::sym;
|
||||
|
||||
use crate::utils::{is_entrypoint_fn, snippet, span_help_and_lint};
|
||||
use if_chain::if_chain;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for recursion using the entrypoint.
|
||||
///
|
||||
/// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
|
||||
/// recursing into main() seems like an unintuitive antipattern we should be able to detect.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```no_run
|
||||
/// fn main() {
|
||||
/// main();
|
||||
/// }
|
||||
/// ```
|
||||
pub MAIN_RECURSION,
|
||||
style,
|
||||
"recursion using the entrypoint"
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MainRecursion {
|
||||
has_no_std_attr: bool,
|
||||
}
|
||||
|
||||
impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
|
||||
|
||||
impl LateLintPass<'_, '_> for MainRecursion {
|
||||
fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate) {
|
||||
self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std);
|
||||
}
|
||||
|
||||
fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) {
|
||||
if self.has_no_std_attr {
|
||||
return;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
if let ExprKind::Call(func, _) = &expr.node;
|
||||
if let ExprKind::Path(path) = &func.node;
|
||||
if let QPath::Resolved(_, path) = &path;
|
||||
if let Some(def_id) = path.res.opt_def_id();
|
||||
if is_entrypoint_fn(cx, def_id);
|
||||
then {
|
||||
span_help_and_lint(
|
||||
cx,
|
||||
MAIN_RECURSION,
|
||||
func.span,
|
||||
&format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
|
||||
"consider using another function for this recursion"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ pub use lint::Lint;
|
||||
pub use lint::LINT_LEVELS;
|
||||
|
||||
// begin lint list, do not remove this comment, it’s used in `update_lints`
|
||||
pub const ALL_LINTS: [Lint; 309] = [
|
||||
pub const ALL_LINTS: [Lint; 310] = [
|
||||
Lint {
|
||||
name: "absurd_extreme_comparisons",
|
||||
group: "correctness",
|
||||
@ -917,6 +917,13 @@ pub const ALL_LINTS: [Lint; 309] = [
|
||||
deprecation: None,
|
||||
module: "booleans",
|
||||
},
|
||||
Lint {
|
||||
name: "main_recursion",
|
||||
group: "style",
|
||||
desc: "recursion using the entrypoint",
|
||||
deprecation: None,
|
||||
module: "main_recursion",
|
||||
},
|
||||
Lint {
|
||||
name: "manual_memcpy",
|
||||
group: "perf",
|
||||
|
12
tests/ui/crate_level_checks/entrypoint_recursion.rs
Normal file
12
tests/ui/crate_level_checks/entrypoint_recursion.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// ignore-macos
|
||||
// ignore-windows
|
||||
|
||||
#![feature(main)]
|
||||
|
||||
#[warn(clippy::main_recursion)]
|
||||
#[allow(unconditional_recursion)]
|
||||
#[main]
|
||||
fn a() {
|
||||
println!("Hello, World!");
|
||||
a();
|
||||
}
|
11
tests/ui/crate_level_checks/entrypoint_recursion.stderr
Normal file
11
tests/ui/crate_level_checks/entrypoint_recursion.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: recursing into entrypoint `a`
|
||||
--> $DIR/entrypoint_recursion.rs:11:5
|
||||
|
|
||||
LL | a();
|
||||
| ^
|
||||
|
|
||||
= note: `-D clippy::main-recursion` implied by `-D warnings`
|
||||
= help: consider using another function for this recursion
|
||||
|
||||
error: aborting due to previous error
|
||||
|
33
tests/ui/crate_level_checks/no_std_main_recursion.rs
Normal file
33
tests/ui/crate_level_checks/no_std_main_recursion.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// ignore-macos
|
||||
// ignore-windows
|
||||
|
||||
#![feature(lang_items, link_args, start, libc)]
|
||||
#![link_args = "-nostartfiles"]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static N: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[warn(clippy::main_recursion)]
|
||||
#[start]
|
||||
fn main(argc: isize, argv: *const *const u8) -> isize {
|
||||
let x = N.load(Ordering::Relaxed);
|
||||
N.store(x + 1, Ordering::Relaxed);
|
||||
|
||||
if x < 3 {
|
||||
main(argc, argv);
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
extern "C" fn eh_personality() {}
|
6
tests/ui/crate_level_checks/std_main_recursion.rs
Normal file
6
tests/ui/crate_level_checks/std_main_recursion.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#[warn(clippy::main_recursion)]
|
||||
#[allow(unconditional_recursion)]
|
||||
fn main() {
|
||||
println!("Hello, World!");
|
||||
main();
|
||||
}
|
11
tests/ui/crate_level_checks/std_main_recursion.stderr
Normal file
11
tests/ui/crate_level_checks/std_main_recursion.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: recursing into entrypoint `main`
|
||||
--> $DIR/std_main_recursion.rs:5:5
|
||||
|
|
||||
LL | main();
|
||||
| ^^^^
|
||||
|
|
||||
= note: `-D clippy::main-recursion` implied by `-D warnings`
|
||||
= help: consider using another function for this recursion
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user