1 use clippy_utils
::diagnostics
::span_lint_and_help
;
2 use clippy_utils
::source
::snippet
;
3 use clippy_utils
::{is_entrypoint_fn, is_no_std_crate}
;
4 use if_chain
::if_chain
;
5 use rustc_hir
::{Crate, Expr, ExprKind, QPath}
;
6 use rustc_lint
::{LateContext, LateLintPass}
;
7 use rustc_session
::{declare_tool_lint, impl_lint_pass}
;
10 /// **What it does:** Checks for recursion using the entrypoint.
12 /// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]),
13 /// recursing into main() seems like an unintuitive antipattern we should be able to detect.
15 /// **Known problems:** None.
25 "recursion using the entrypoint"
29 pub struct MainRecursion
{
30 has_no_std_attr
: bool
,
33 impl_lint_pass
!(MainRecursion
=> [MAIN_RECURSION
]);
35 impl LateLintPass
<'_
> for MainRecursion
{
36 fn check_crate(&mut self, cx
: &LateContext
<'_
>, _
: &Crate
<'_
>) {
37 self.has_no_std_attr
= is_no_std_crate(cx
);
40 fn check_expr_post(&mut self, cx
: &LateContext
<'_
>, expr
: &Expr
<'_
>) {
41 if self.has_no_std_attr
{
46 if let ExprKind
::Call(func
, _
) = &expr
.kind
;
47 if let ExprKind
::Path(QPath
::Resolved(_
, path
)) = &func
.kind
;
48 if let Some(def_id
) = path
.res
.opt_def_id();
49 if is_entrypoint_fn(cx
, def_id
);
55 &format
!("recursing into entrypoint `{}`", snippet(cx
, func
.span
, "main")),
57 "consider using another function for this recursion"