]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
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 | } |