]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/loops/missing_spin_loop.rs
Merge commit 'dc5423ad448877e33cca28db2f1445c9c4473c75' into clippyup
[rust.git] / clippy_lints / src / loops / missing_spin_loop.rs
1 use super::MISSING_SPIN_LOOP;
2 use clippy_utils::diagnostics::span_lint_and_sugg;
3 use clippy_utils::is_no_std_crate;
4 use rustc_errors::Applicability;
5 use rustc_hir::{Block, Expr, ExprKind};
6 use rustc_lint::LateContext;
7 use rustc_middle::ty;
8 use rustc_span::sym;
9
10 fn unpack_cond<'tcx>(cond: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
11     match &cond.kind {
12         ExprKind::Block(
13             Block {
14                 stmts: [],
15                 expr: Some(e),
16                 ..
17             },
18             _,
19         )
20         | ExprKind::Unary(_, e) => unpack_cond(e),
21         ExprKind::Binary(_, l, r) => {
22             let l = unpack_cond(l);
23             if let ExprKind::MethodCall(..) = l.kind {
24                 l
25             } else {
26                 unpack_cond(r)
27             }
28         },
29         _ => cond,
30     }
31 }
32
33 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>) {
34     if_chain! {
35         if let ExprKind::Block(Block { stmts: [], expr: None, ..}, _) = body.kind;
36         if let ExprKind::MethodCall(method, [callee, ..], _) = unpack_cond(cond).kind;
37         if [sym::load, sym::compare_exchange, sym::compare_exchange_weak].contains(&method.ident.name);
38         if let ty::Adt(def, _substs) = cx.typeck_results().expr_ty(callee).kind();
39         if cx.tcx.is_diagnostic_item(sym::AtomicBool, def.did());
40         then {
41             span_lint_and_sugg(
42                 cx,
43                 MISSING_SPIN_LOOP,
44                 body.span,
45                 "busy-waiting loop should at least have a spin loop hint",
46                 "try this",
47                 (if is_no_std_crate(cx) {
48                     "{ core::hint::spin_loop() }"
49                 } else {
50                     "{ std::hint::spin_loop() }"
51                 }).into(),
52                 Applicability::MachineApplicable
53             );
54         }
55     }
56 }