1 use clippy_utils
::diagnostics
::span_lint
;
2 use clippy_utils
::{is_entrypoint_fn, match_def_path, paths}
;
3 use if_chain
::if_chain
;
4 use rustc_hir
::{Expr, ExprKind, Item, ItemKind, Node}
;
5 use rustc_lint
::{LateContext, LateLintPass}
;
6 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
10 /// Detects calls to the `exit()` function which terminates the program.
12 /// ### Why is this bad?
13 /// Exit terminates the program at the location it is called. For unrecoverable
14 /// errors `panics` should be used to provide a stacktrace and potentially other
15 /// information. A normal termination or one with an error code should happen in
16 /// the main function.
20 /// std::process::exit(0)
26 /// // To provide a stacktrace and additional information
27 /// panic!("message");
29 /// // or a main method with a return
30 /// fn main() -> Result<(), i32> {
34 #[clippy::version = "1.41.0"]
37 "detects `std::process::exit` calls"
40 declare_lint_pass
!(Exit
=> [EXIT
]);
42 impl<'tcx
> LateLintPass
<'tcx
> for Exit
{
43 fn check_expr(&mut self, cx
: &LateContext
<'tcx
>, e
: &'tcx Expr
<'_
>) {
45 if let ExprKind
::Call(path_expr
, _args
) = e
.kind
;
46 if let ExprKind
::Path(ref path
) = path_expr
.kind
;
47 if let Some(def_id
) = cx
.qpath_res(path
, path_expr
.hir_id
).opt_def_id();
48 if match_def_path(cx
, def_id
, &paths
::EXIT
);
49 let parent
= cx
.tcx
.hir().get_parent_item(e
.hir_id
).def_id
;
50 if let Some(Node
::Item(Item{kind: ItemKind::Fn(..), ..}
)) = cx
.tcx
.hir().find_by_def_id(parent
);
51 // If the next item up is a function we check if it is an entry point
52 // and only then emit a linter warning
53 if !is_entrypoint_fn(cx
, parent
.to_def_id());
55 span_lint(cx
, EXIT
, e
.span
, "usage of `process::exit`");