Skip to content

Commit 89a44aa

Browse files
committed
Move PtrEq into Operators lin pass
1 parent ecc61c7 commit 89a44aa

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
@@ -254,6 +254,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
254254
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
255255
LintId::of(operators::MODULO_ONE),
256256
LintId::of(operators::OP_REF),
257+
LintId::of(operators::PTR_EQ),
257258
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
258259
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
259260
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
@@ -262,7 +263,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
262263
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
263264
LintId::of(ptr::MUT_FROM_REF),
264265
LintId::of(ptr::PTR_ARG),
265-
LintId::of(ptr_eq::PTR_EQ),
266266
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
267267
LintId::of(question_mark::QUESTION_MARK),
268268
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
@@ -426,6 +426,7 @@ store.register_lints(&[
426426
operators::MODULO_ONE,
427427
operators::NEEDLESS_BITWISE_BOOL,
428428
operators::OP_REF,
429+
operators::PTR_EQ,
429430
operators::VERBOSE_BIT_MASK,
430431
option_env_unwrap::OPTION_ENV_UNWRAP,
431432
option_if_let_else::OPTION_IF_LET_ELSE,
@@ -445,7 +446,6 @@ store.register_lints(&[
445446
ptr::INVALID_NULL_PTR_USAGE,
446447
ptr::MUT_FROM_REF,
447448
ptr::PTR_ARG,
448-
ptr_eq::PTR_EQ,
449449
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
450450
pub_use::PUB_USE,
451451
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
@@ -334,7 +334,6 @@ mod path_buf_push_overwrite;
334334
mod pattern_type_mismatch;
335335
mod precedence;
336336
mod ptr;
337-
mod ptr_eq;
338337
mod ptr_offset_with_cast;
339338
mod pub_use;
340339
mod question_mark;
@@ -539,7 +538,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
539538
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
540539
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
541540
store.register_late_pass(|| Box::new(ptr::Ptr));
542-
store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
543541
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
544542
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
545543
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! {
@@ -670,6 +671,35 @@ declare_clippy_lint! {
670671
"Boolean expressions that use bitwise rather than lazy operators"
671672
}
672673

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