]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
Merge branch 'master' of http://localhost:8000/rust-lang/rust.git:at_commit=75dd959a3...
[rust.git] / src / tools / clippy / clippy_lints / src / operators / ptr_eq.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet_opt;
3 use if_chain::if_chain;
4 use rustc_errors::Applicability;
5 use rustc_hir::{BinOpKind, Expr, ExprKind};
6 use rustc_lint::LateContext;
7
8 use super::PTR_EQ;
9
10 static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
11
12 pub(super) fn check<'tcx>(
13     cx: &LateContext<'tcx>,
14     expr: &'tcx Expr<'_>,
15     op: BinOpKind,
16     left: &'tcx Expr<'_>,
17     right: &'tcx Expr<'_>,
18 ) {
19     if BinOpKind::Eq == op {
20         let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
21             (Some(lhs), Some(rhs)) => (lhs, rhs),
22             _ => (left, right),
23         };
24
25         if_chain! {
26             if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left);
27             if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right);
28             if let Some(left_snip) = snippet_opt(cx, left_var.span);
29             if let Some(right_snip) = snippet_opt(cx, right_var.span);
30             then {
31                 span_lint_and_sugg(
32                     cx,
33                     PTR_EQ,
34                     expr.span,
35                     LINT_MSG,
36                     "try",
37                     format!("std::ptr::eq({left_snip}, {right_snip})"),
38                     Applicability::MachineApplicable,
39                     );
40             }
41         }
42     }
43 }
44
45 // If the given expression is a cast to a usize, return the lhs of the cast
46 // E.g., `foo as *const _ as usize` returns `foo as *const _`.
47 fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
48     if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize {
49         if let ExprKind::Cast(expr, _) = cast_expr.kind {
50             return Some(expr);
51         }
52     }
53     None
54 }
55
56 // If the given expression is a cast to a `*const` pointer, return the lhs of the cast
57 // E.g., `foo as *const _` returns `foo`.
58 fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
59     if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() {
60         if let ExprKind::Cast(expr, _) = cast_expr.kind {
61             return Some(expr);
62         }
63     }
64     None
65 }