use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::root_macro_call_first_node;
+use clippy_utils::return_ty;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{find_macro_calls, is_expn_of, return_ty};
+use clippy_utils::visitors::{for_each_expr, Descend};
+use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LateLintPass};
/// Err(String::from("error"))
/// }
/// ```
+ #[clippy::version = "1.48.0"]
pub PANIC_IN_RESULT_FN,
restriction,
"functions of type `Result<..>` that contain `panic!()`, `todo!()`, `unreachable()`, `unimplemented()` or assertion"
}
fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
- let mut panics = find_macro_calls(
- &[
- "unimplemented",
- "unreachable",
- "panic",
- "todo",
- "assert",
- "assert_eq",
- "assert_ne",
- ],
- body,
- );
- panics.retain(|span| is_expn_of(*span, "debug_assert").is_none());
+ let mut panics = Vec::new();
+ let _: Option<!> = for_each_expr(body.value, |e| {
+ let Some(macro_call) = root_macro_call_first_node(cx, e) else {
+ return ControlFlow::Continue(Descend::Yes);
+ };
+ if matches!(
+ cx.tcx.item_name(macro_call.def_id).as_str(),
+ "unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne"
+ ) {
+ panics.push(macro_call.span);
+ ControlFlow::Continue(Descend::No)
+ } else {
+ ControlFlow::Continue(Descend::Yes)
+ }
+ });
if !panics.is_empty() {
span_lint_and_then(
cx,