Skip to content

Commit 92891a0

Browse files
committed
Move PtrEq into Operators lin pass
1 parent fc5eac5 commit 92891a0

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
@@ -260,6 +260,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
260260
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
261261
LintId::of(operators::MODULO_ONE),
262262
LintId::of(operators::OP_REF),
263+
LintId::of(operators::PTR_EQ),
263264
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
264265
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
265266
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
@@ -268,7 +269,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
268269
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
269270
LintId::of(ptr::MUT_FROM_REF),
270271
LintId::of(ptr::PTR_ARG),
271-
LintId::of(ptr_eq::PTR_EQ),
272272
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
273273
LintId::of(question_mark::QUESTION_MARK),
274274
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
@@ -436,6 +436,7 @@ store.register_lints(&[
436436
operators::MODULO_ONE,
437437
operators::NEEDLESS_BITWISE_BOOL,
438438
operators::OP_REF,
439+
operators::PTR_EQ,
439440
operators::VERBOSE_BIT_MASK,
440441
option_env_unwrap::OPTION_ENV_UNWRAP,
441442
option_if_let_else::OPTION_IF_LET_ELSE,
@@ -455,7 +456,6 @@ store.register_lints(&[
455456
ptr::INVALID_NULL_PTR_USAGE,
456457
ptr::MUT_FROM_REF,
457458
ptr::PTR_ARG,
458-
ptr_eq::PTR_EQ,
459459
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
460460
pub_use::PUB_USE,
461461
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
@@ -98,9 +98,9 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
9898
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
9999
LintId::of(operators::ASSIGN_OP_PATTERN),
100100
LintId::of(operators::OP_REF),
101+
LintId::of(operators::PTR_EQ),
101102
LintId::of(ptr::CMP_NULL),
102103
LintId::of(ptr::PTR_ARG),
103-
LintId::of(ptr_eq::PTR_EQ),
104104
LintId::of(question_mark::QUESTION_MARK),
105105
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
106106
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
@@ -335,7 +335,6 @@ mod path_buf_push_overwrite;
335335
mod pattern_type_mismatch;
336336
mod precedence;
337337
mod ptr;
338-
mod ptr_eq;
339338
mod ptr_offset_with_cast;
340339
mod pub_use;
341340
mod question_mark;
@@ -571,7 +570,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
571570
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
572571
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
573572
store.register_late_pass(|| Box::new(ptr::Ptr));
574-
store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
575573
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
576574
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
577575
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)