1 use clippy_utils
::diagnostics
::span_lint_and_then
;
2 use clippy_utils
::ty
::is_type_diagnostic_item
;
3 use clippy_utils
::{find_macro_calls, is_expn_of, return_ty}
;
5 use rustc_hir
::intravisit
::FnKind
;
6 use rustc_lint
::{LateContext, LateLintPass}
;
7 use rustc_session
::{declare_lint_pass, declare_tool_lint}
;
8 use rustc_span
::{sym, Span}
;
10 declare_clippy_lint
! {
11 /// **What it does:** Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result.
13 /// **Why is this bad?** For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence panicking macros should be avoided.
15 /// **Known problems:** Functions called from a function returning a `Result` may invoke a panicking macro. This is not checked.
20 /// fn result_with_panic() -> Result<bool, String>
27 /// fn result_without_panic() -> Result<bool, String> {
28 /// Err(String::from("error"))
31 pub PANIC_IN_RESULT_FN
,
33 "functions of type `Result<..>` that contain `panic!()`, `todo!()`, `unreachable()`, `unimplemented()` or assertion"
36 declare_lint_pass
!(PanicInResultFn
=> [PANIC_IN_RESULT_FN
]);
38 impl<'tcx
> LateLintPass
<'tcx
> for PanicInResultFn
{
41 cx
: &LateContext
<'tcx
>,
42 fn_kind
: FnKind
<'tcx
>,
43 _
: &'tcx hir
::FnDecl
<'tcx
>,
44 body
: &'tcx hir
::Body
<'tcx
>,
48 if !matches
!(fn_kind
, FnKind
::Closure
) && is_type_diagnostic_item(cx
, return_ty(cx
, hir_id
), sym
::result_type
) {
49 lint_impl_body(cx
, span
, body
);
54 fn lint_impl_body
<'tcx
>(cx
: &LateContext
<'tcx
>, impl_span
: Span
, body
: &'tcx hir
::Body
<'tcx
>) {
55 let mut panics
= find_macro_calls(
67 panics
.retain(|span
| is_expn_of(*span
, "debug_assert").is_none());
68 if !panics
.is_empty() {
73 "used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`",
76 "`unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing",
78 diag
.span_note(panics
, "return Err() instead of panicking");