Skip to content

Commit 0b069c1

Browse files
committed
Move PtrEq into Operators lin pass
1 parent efe72cf commit 0b069c1

File tree

7 files changed

+100
-102
lines changed

7 files changed

+100
-102
lines changed

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
253253
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
254254
LintId::of(operators::MODULO_ONE),
255255
LintId::of(operators::OP_REF),
256+
LintId::of(operators::PTR_EQ),
256257
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
257258
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
258259
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
@@ -261,7 +262,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
261262
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
262263
LintId::of(ptr::MUT_FROM_REF),
263264
LintId::of(ptr::PTR_ARG),
264-
LintId::of(ptr_eq::PTR_EQ),
265265
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
266266
LintId::of(question_mark::QUESTION_MARK),
267267
LintId::of(ranges::MANUAL_RANGE_CONTAINS),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ store.register_lints(&[
424424
operators::MODULO_ONE,
425425
operators::NEEDLESS_BITWISE_BOOL,
426426
operators::OP_REF,
427+
operators::PTR_EQ,
427428
operators::VERBOSE_BIT_MASK,
428429
option_env_unwrap::OPTION_ENV_UNWRAP,
429430
option_if_let_else::OPTION_IF_LET_ELSE,
@@ -443,7 +444,6 @@ store.register_lints(&[
443444
ptr::INVALID_NULL_PTR_USAGE,
444445
ptr::MUT_FROM_REF,
445446
ptr::PTR_ARG,
446-
ptr_eq::PTR_EQ,
447447
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
448448
pub_use::PUB_USE,
449449
question_mark::QUESTION_MARK,

clippy_lints/src/lib.register_style.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
9696
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
9797
LintId::of(operators::ASSIGN_OP_PATTERN),
9898
LintId::of(operators::OP_REF),
99+
LintId::of(operators::PTR_EQ),
99100
LintId::of(ptr::CMP_NULL),
100101
LintId::of(ptr::PTR_ARG),
101-
LintId::of(ptr_eq::PTR_EQ),
102102
LintId::of(question_mark::QUESTION_MARK),
103103
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
104104
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ mod path_buf_push_overwrite;
332332
mod pattern_type_mismatch;
333333
mod precedence;
334334
mod ptr;
335-
mod ptr_eq;
336335
mod ptr_offset_with_cast;
337336
mod pub_use;
338337
mod question_mark;
@@ -537,7 +536,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
537536
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
538537
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
539538
store.register_late_pass(|| Box::new(ptr::Ptr));
540-
store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
541539
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
542540
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
543541
store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));

clippy_lints/src/operators/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ mod modulo_arithmetic;
2121
mod modulo_one;
2222
mod needless_bitwise_bool;
2323
mod op_ref;
24+
mod ptr_eq;
2425
mod verbose_bit_mask;
2526

2627
declare_clippy_lint! {
@@ -656,6 +657,35 @@ declare_clippy_lint! {
656657
"Boolean expressions that use bitwise rather than lazy operators"
657658
}
658659

660+
declare_clippy_lint! {
661+
/// ### What it does
662+
/// Use `std::ptr::eq` when applicable
663+
///
664+
/// ### Why is this bad?
665+
/// `ptr::eq` can be used to compare `&T` references
666+
/// (which coerce to `*const T` implicitly) by their address rather than
667+
/// comparing the values they point to.
668+
///
669+
/// ### Example
670+
/// ```rust
671+
/// let a = &[1, 2, 3];
672+
/// let b = &[1, 2, 3];
673+
///
674+
/// assert!(a as *const _ as usize == b as *const _ as usize);
675+
/// ```
676+
/// Use instead:
677+
/// ```rust
678+
/// let a = &[1, 2, 3];
679+
/// let b = &[1, 2, 3];
680+
///
681+
/// assert!(std::ptr::eq(a, b));
682+
/// ```
683+
#[clippy::version = "1.49.0"]
684+
pub PTR_EQ,
685+
style,
686+
"use `std::ptr::eq` when comparing raw pointers"
687+
}
688+
659689
pub struct Operators {
660690
arithmetic_context: arithmetic::Context,
661691
verbose_bit_mask_threshold: u64,
@@ -684,6 +714,7 @@ impl_lint_pass!(Operators => [
684714
MODULO_ONE,
685715
MODULO_ARITHMETIC,
686716
NEEDLESS_BITWISE_BOOL,
717+
PTR_EQ,
687718
]);
688719
impl Operators {
689720
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
@@ -707,6 +738,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
707738
erasing_op::check(cx, e, op.node, lhs, rhs);
708739
identity_op::check(cx, e, op.node, lhs, rhs);
709740
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
741+
ptr_eq::check(cx, e, op.node, lhs, rhs);
710742
}
711743
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
712744
bit_mask::check(cx, e, op.node, lhs, rhs);

clippy_lints/src/operators/ptr_eq.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
}

clippy_lints/src/ptr_eq.rs

Lines changed: 0 additions & 97 deletions
This file was deleted.

0 commit comments

Comments
 (0)