Skip to content

Commit

Permalink
Move expression check to LateLintPass
Browse files Browse the repository at this point in the history
Changes:
- Move from EarlyLintPass
- Fix entrypoint check with function path def_id.
  • Loading branch information
Vincent Dal Maso committed Jun 17, 2019
1 parent 6804156 commit 73978a1
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 18 deletions.
4 changes: 3 additions & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,8 @@ 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_early_lint_pass(box main_recursion::MainRecursion::new());
// reg.register_early_lint_pass(box main_recursion::MainRecursion::new());
reg.register_late_lint_pass(box main_recursion::MainRecursion::new());
reg.register_late_lint_pass(box lifetimes::Lifetimes);
reg.register_late_lint_pass(box entry::HashMapPass);
reg.register_late_lint_pass(box ranges::Ranges);
Expand Down Expand Up @@ -916,6 +917,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
let_if_seq::USELESS_LET_IF_SEQ,
literal_representation::INCONSISTENT_DIGIT_GROUPING,
literal_representation::UNREADABLE_LITERAL,
main_recursion::MAIN_RECURSION,
loops::EMPTY_LOOP,
loops::FOR_KV_MAP,
loops::NEEDLESS_RANGE_LOOP,
Expand Down
42 changes: 29 additions & 13 deletions clippy_lints/src/main_recursion.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@

use syntax::ast::{Crate, Expr, ExprKind};
use syntax::symbol::sym;
use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext};
use rustc::lint::{LintArray, LintPass, LateLintPass, LateContext};
use rustc::hir::{Crate, Expr, ExprKind, QPath};
use rustc::hir::def::Res;
use rustc::{declare_tool_lint, impl_lint_pass};

use if_chain::if_chain;
use crate::utils::span_help_and_lint;
use crate::utils::{span_help_and_lint, is_entrypoint_fn};

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,
pedantic,
"function named `foo`, which is not a descriptive name"
style,
"recursion using the entrypoint"
}

pub struct MainRecursion {
Expand All @@ -27,27 +41,29 @@ impl MainRecursion {
}
}

impl EarlyLintPass for MainRecursion {
fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
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(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
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 *path == sym::main;
if let ExprKind::Path(path) = &func.node;
if let QPath::Resolved(_, ptr) = &path;
if let Res::Def(_, def_id) = &ptr.res;
if is_entrypoint_fn(cx, *def_id);
then {
span_help_and_lint(
cx,
MAIN_RECURSION,
expr.span,
"You are recursing into main()",
"Consider using another function for this recursion"
func.span,
"recursing into `main()`",
"consider using another function for this recursion"
)
}
}
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/crate_level_checks/entrypoint_recursion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![feature(main)]

#[warn(clippy::main_recursion)]
#[allow(unconditional_recursion)]
#[main]
fn a() {
println!("Hello, World!");
a();
}
11 changes: 11 additions & 0 deletions tests/ui/crate_level_checks/entrypoint_recursion.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: recursing into `main()`
--> $DIR/entrypoint_recursion.rs:8: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

Empty file.
1 change: 1 addition & 0 deletions tests/ui/crate_level_checks/std_main_recursion.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[warn(clippy::main_recursion)]
#[allow(unconditional_recursion)]
fn main() {
println!("Hello, World!");
main();
}
8 changes: 4 additions & 4 deletions tests/ui/crate_level_checks/std_main_recursion.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: You are recursing into main()
--> $DIR/std_main_recursion.rs:4:5
error: recursing into `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
= help: consider using another function for this recursion

error: aborting due to previous error

0 comments on commit 73978a1

Please sign in to comment.