]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/main_recursion.rs
1b274c79d3820b5a948efb4578adb3bf220b0e3f
[rust.git] / clippy_lints / src / main_recursion.rs
1 use rustc_hir::{Crate, Expr, ExprKind, QPath};
2 use rustc_lint::{LateContext, LateLintPass};
3 use rustc_session::{declare_tool_lint, impl_lint_pass};
4
5 use crate::utils::{is_entrypoint_fn, is_no_std_crate, snippet, span_lint_and_help};
6 use if_chain::if_chain;
7
8 declare_clippy_lint! {
9     /// **What it does:** Checks for recursion using the entrypoint.
10     ///
11     /// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
12     /// recursing into main() seems like an unintuitive antipattern we should be able to detect.
13     ///
14     /// **Known problems:** None.
15     ///
16     /// **Example:**
17     /// ```no_run
18     /// fn main() {
19     ///     main();
20     /// }
21     /// ```
22     pub MAIN_RECURSION,
23     style,
24     "recursion using the entrypoint"
25 }
26
27 #[derive(Default)]
28 pub struct MainRecursion {
29     has_no_std_attr: bool,
30 }
31
32 impl_lint_pass!(MainRecursion => [MAIN_RECURSION]);
33
34 impl LateLintPass<'_> for MainRecursion {
35     fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
36         self.has_no_std_attr = is_no_std_crate(cx);
37     }
38
39     fn check_expr_post(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
40         if self.has_no_std_attr {
41             return;
42         }
43
44         if_chain! {
45             if let ExprKind::Call(func, _) = &expr.kind;
46             if let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind;
47             if let Some(def_id) = path.res.opt_def_id();
48             if is_entrypoint_fn(cx, def_id);
49             then {
50                 span_lint_and_help(
51                     cx,
52                     MAIN_RECURSION,
53                     func.span,
54                     &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")),
55                     None,
56                     "consider using another function for this recursion"
57                 )
58             }
59         }
60     }
61 }