| use super::EMPTY_LOOP; | |
| use clippy_utils::diagnostics::span_lint_and_help; | |
| use clippy_utils::{is_in_panic_handler, is_no_std_crate}; | |
| use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; | |
| use rustc_lint::LateContext; | |
| pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_>) { | |
| let parent_hir_id = cx.tcx.parent_hir_id(expr.hir_id); | |
| if let Node::Item(parent_node) = cx.tcx.hir_node(parent_hir_id) | |
| && matches!(parent_node.kind, ItemKind::Fn { .. }) | |
| && let attrs = cx.tcx.hir_attrs(parent_hir_id) | |
| && find_attr!(attrs, RustcIntrinsic) | |
| { | |
| // Intrinsic functions are expanded into an empty loop when lowering the AST | |
| // to simplify the job of later passes which might expect any function to have a body. | |
| return; | |
| } | |
| if loop_block.stmts.is_empty() && loop_block.expr.is_none() && !is_in_panic_handler(cx, expr) { | |
| let msg = "empty `loop {}` wastes CPU cycles"; | |
| let help = if is_no_std_crate(cx) { | |
| "you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body" | |
| } else { | |
| "you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body" | |
| }; | |
| span_lint_and_help(cx, EMPTY_LOOP, expr.span, msg, None, help); | |
| } | |
| } |