1 use clippy_utils::diagnostics::span_lint;
2 use clippy_utils::{is_expn_of, match_panic_call};
3 use if_chain::if_chain;
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
11 /// Checks for usage of `panic!`.
13 /// ### Why is this bad?
14 /// `panic!` will stop the execution of the executable
18 /// panic!("even with a good reason");
20 #[clippy::version = "1.40.0"]
23 "usage of the `panic!` macro"
26 declare_clippy_lint! {
28 /// Checks for usage of `unimplemented!`.
30 /// ### Why is this bad?
31 /// This macro should not be present in production code
37 #[clippy::version = "pre 1.29.0"]
40 "`unimplemented!` should not be present in production code"
43 declare_clippy_lint! {
45 /// Checks for usage of `todo!`.
47 /// ### Why is this bad?
48 /// This macro should not be present in production code
54 #[clippy::version = "1.40.0"]
57 "`todo!` should not be present in production code"
60 declare_clippy_lint! {
62 /// Checks for usage of `unreachable!`.
64 /// ### Why is this bad?
65 /// This macro can cause code to panic
71 #[clippy::version = "1.40.0"]
74 "usage of the `unreachable!` macro"
77 declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
79 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
80 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
81 if match_panic_call(cx, expr).is_some()
82 && (is_expn_of(expr.span, "debug_assert").is_none() && is_expn_of(expr.span, "assert").is_none())
84 let span = get_outer_span(expr);
85 if is_expn_of(expr.span, "unimplemented").is_some() {
90 "`unimplemented` should not be present in production code",
92 } else if is_expn_of(expr.span, "todo").is_some() {
93 span_lint(cx, TODO, span, "`todo` should not be present in production code");
94 } else if is_expn_of(expr.span, "unreachable").is_some() {
95 span_lint(cx, UNREACHABLE, span, "usage of the `unreachable!` macro");
96 } else if is_expn_of(expr.span, "panic").is_some() {
97 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
103 fn get_outer_span(expr: &Expr<'_>) -> Span {
105 if expr.span.from_expansion();
106 let first = expr.span.ctxt().outer_expn_data().call_site;
107 if first.from_expansion();
109 first.ctxt().outer_expn_data().call_site