Skip to content

Commit 3e943c9

Browse files
committed
Move PtrEq into Operators lin pass
1 parent 12579a2 commit 3e943c9

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
@@ -256,6 +256,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
256256
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
257257
LintId::of(operators::MODULO_ONE),
258258
LintId::of(operators::OP_REF),
259+
LintId::of(operators::PTR_EQ),
259260
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
260261
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
261262
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
@@ -264,7 +265,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
264265
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
265266
LintId::of(ptr::MUT_FROM_REF),
266267
LintId::of(ptr::PTR_ARG),
267-
LintId::of(ptr_eq::PTR_EQ),
268268
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
269269
LintId::of(question_mark::QUESTION_MARK),
270270
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
@@ -430,6 +430,7 @@ store.register_lints(&[
430430
operators::MODULO_ONE,
431431
operators::NEEDLESS_BITWISE_BOOL,
432432
operators::OP_REF,
433+
operators::PTR_EQ,
433434
operators::VERBOSE_BIT_MASK,
434435
option_env_unwrap::OPTION_ENV_UNWRAP,
435436
option_if_let_else::OPTION_IF_LET_ELSE,
@@ -449,7 +450,6 @@ store.register_lints(&[
449450
ptr::INVALID_NULL_PTR_USAGE,
450451
ptr::MUT_FROM_REF,
451452
ptr::PTR_ARG,
452-
ptr_eq::PTR_EQ,
453453
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
454454
pub_use::PUB_USE,
455455
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
@@ -97,9 +97,9 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
9797
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
9898
LintId::of(operators::ASSIGN_OP_PATTERN),
9999
LintId::of(operators::OP_REF),
100+
LintId::of(operators::PTR_EQ),
100101
LintId::of(ptr::CMP_NULL),
101102
LintId::of(ptr::PTR_ARG),
102-
LintId::of(ptr_eq::PTR_EQ),
103103
LintId::of(question_mark::QUESTION_MARK),
104104
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
105105
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;
@@ -535,7 +534,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
535534
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
536535
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
537536
store.register_late_pass(|| Box::new(ptr::Ptr));
538-
store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
539537
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
540538
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
541539
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_one;
2121
mod needless_bitwise_bool;
2222
mod numeric_arithmetic;
2323
mod op_ref;
24+
mod ptr_eq;
2425
mod verbose_bit_mask;
2526

2627
declare_clippy_lint! {
@@ -671,6 +672,35 @@ declare_clippy_lint! {
671672
"Boolean expressions that use bitwise rather than lazy operators"
672673
}
673674

675+
declare_clippy_lint! {
676+
/// ### What it does
677+
/// Use `std::ptr::eq` when applicable
678+
///
679+
/// ### Why is this bad?
680+
/// `ptr::eq` can be used to compare `&T` references
681+
/// (which coerce to `*const T` implicitly) by their address rather than
682+
/// comparing the values they point to.
683+
///
684+
/// ### Example
685+
/// ```rust
686+
/// let a = &[1, 2, 3];
687+
/// let b = &[1, 2, 3];
688+
///
689+
/// assert!(a as *const _ as usize == b as *const _ as usize);
690+
/// ```
691+
/// Use instead:
692+
/// ```rust
693+
/// let a = &[1, 2, 3];
694+
/// let b = &[1, 2, 3];
695+
///
696+
/// assert!(std::ptr::eq(a, b));
697+
/// ```
698+
#[clippy::version = "1.49.0"]
699+
pub PTR_EQ,
700+
style,
701+
"use `std::ptr::eq` when comparing raw pointers"
702+
}
703+
674704
pub struct Operators {
675705
arithmetic_context: numeric_arithmetic::Context,
676706
verbose_bit_mask_threshold: u64,
@@ -699,6 +729,7 @@ impl_lint_pass!(Operators => [
699729
MODULO_ONE,
700730
MODULO_ARITHMETIC,
701731
NEEDLESS_BITWISE_BOOL,
732+
PTR_EQ,
702733
]);
703734
impl Operators {
704735
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
@@ -722,6 +753,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
722753
erasing_op::check(cx, e, op.node, lhs, rhs);
723754
identity_op::check(cx, e, op.node, lhs, rhs);
724755
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
756+
ptr_eq::check(cx, e, op.node, lhs, rhs);
725757
}
726758
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
727759
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)