Move PtrEq
into Operators
lin pass
This commit is contained in:
parent
fc5eac5894
commit
92891a01a1
@ -260,6 +260,7 @@
|
|||||||
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
|
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
|
||||||
LintId::of(operators::MODULO_ONE),
|
LintId::of(operators::MODULO_ONE),
|
||||||
LintId::of(operators::OP_REF),
|
LintId::of(operators::OP_REF),
|
||||||
|
LintId::of(operators::PTR_EQ),
|
||||||
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
|
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
|
||||||
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
|
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
|
||||||
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
||||||
@ -268,7 +269,6 @@
|
|||||||
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
|
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
|
||||||
LintId::of(ptr::MUT_FROM_REF),
|
LintId::of(ptr::MUT_FROM_REF),
|
||||||
LintId::of(ptr::PTR_ARG),
|
LintId::of(ptr::PTR_ARG),
|
||||||
LintId::of(ptr_eq::PTR_EQ),
|
|
||||||
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
LintId::of(ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
|
||||||
LintId::of(question_mark::QUESTION_MARK),
|
LintId::of(question_mark::QUESTION_MARK),
|
||||||
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
||||||
|
@ -436,6 +436,7 @@
|
|||||||
operators::MODULO_ONE,
|
operators::MODULO_ONE,
|
||||||
operators::NEEDLESS_BITWISE_BOOL,
|
operators::NEEDLESS_BITWISE_BOOL,
|
||||||
operators::OP_REF,
|
operators::OP_REF,
|
||||||
|
operators::PTR_EQ,
|
||||||
operators::VERBOSE_BIT_MASK,
|
operators::VERBOSE_BIT_MASK,
|
||||||
option_env_unwrap::OPTION_ENV_UNWRAP,
|
option_env_unwrap::OPTION_ENV_UNWRAP,
|
||||||
option_if_let_else::OPTION_IF_LET_ELSE,
|
option_if_let_else::OPTION_IF_LET_ELSE,
|
||||||
@ -455,7 +456,6 @@
|
|||||||
ptr::INVALID_NULL_PTR_USAGE,
|
ptr::INVALID_NULL_PTR_USAGE,
|
||||||
ptr::MUT_FROM_REF,
|
ptr::MUT_FROM_REF,
|
||||||
ptr::PTR_ARG,
|
ptr::PTR_ARG,
|
||||||
ptr_eq::PTR_EQ,
|
|
||||||
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
|
ptr_offset_with_cast::PTR_OFFSET_WITH_CAST,
|
||||||
pub_use::PUB_USE,
|
pub_use::PUB_USE,
|
||||||
question_mark::QUESTION_MARK,
|
question_mark::QUESTION_MARK,
|
||||||
|
@ -98,9 +98,9 @@
|
|||||||
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
|
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
|
||||||
LintId::of(operators::ASSIGN_OP_PATTERN),
|
LintId::of(operators::ASSIGN_OP_PATTERN),
|
||||||
LintId::of(operators::OP_REF),
|
LintId::of(operators::OP_REF),
|
||||||
|
LintId::of(operators::PTR_EQ),
|
||||||
LintId::of(ptr::CMP_NULL),
|
LintId::of(ptr::CMP_NULL),
|
||||||
LintId::of(ptr::PTR_ARG),
|
LintId::of(ptr::PTR_ARG),
|
||||||
LintId::of(ptr_eq::PTR_EQ),
|
|
||||||
LintId::of(question_mark::QUESTION_MARK),
|
LintId::of(question_mark::QUESTION_MARK),
|
||||||
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
|
||||||
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
|
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
|
||||||
|
@ -335,7 +335,6 @@ macro_rules! declare_clippy_lint {
|
|||||||
mod pattern_type_mismatch;
|
mod pattern_type_mismatch;
|
||||||
mod precedence;
|
mod precedence;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod ptr_eq;
|
|
||||||
mod ptr_offset_with_cast;
|
mod ptr_offset_with_cast;
|
||||||
mod pub_use;
|
mod pub_use;
|
||||||
mod question_mark;
|
mod question_mark;
|
||||||
@ -571,7 +570,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
|
store.register_late_pass(|| Box::new(enum_clike::UnportableVariant));
|
||||||
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
|
store.register_late_pass(|| Box::new(float_literal::FloatLiteral));
|
||||||
store.register_late_pass(|| Box::new(ptr::Ptr));
|
store.register_late_pass(|| Box::new(ptr::Ptr));
|
||||||
store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
|
|
||||||
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
|
store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
|
||||||
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
|
store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
|
||||||
store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));
|
store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
mod needless_bitwise_bool;
|
mod needless_bitwise_bool;
|
||||||
mod numeric_arithmetic;
|
mod numeric_arithmetic;
|
||||||
mod op_ref;
|
mod op_ref;
|
||||||
|
mod ptr_eq;
|
||||||
mod verbose_bit_mask;
|
mod verbose_bit_mask;
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
@ -671,6 +672,35 @@
|
|||||||
"Boolean expressions that use bitwise rather than lazy operators"
|
"Boolean expressions that use bitwise rather than lazy operators"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_clippy_lint! {
|
||||||
|
/// ### What it does
|
||||||
|
/// Use `std::ptr::eq` when applicable
|
||||||
|
///
|
||||||
|
/// ### Why is this bad?
|
||||||
|
/// `ptr::eq` can be used to compare `&T` references
|
||||||
|
/// (which coerce to `*const T` implicitly) by their address rather than
|
||||||
|
/// comparing the values they point to.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// let a = &[1, 2, 3];
|
||||||
|
/// let b = &[1, 2, 3];
|
||||||
|
///
|
||||||
|
/// assert!(a as *const _ as usize == b as *const _ as usize);
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// let a = &[1, 2, 3];
|
||||||
|
/// let b = &[1, 2, 3];
|
||||||
|
///
|
||||||
|
/// assert!(std::ptr::eq(a, b));
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.49.0"]
|
||||||
|
pub PTR_EQ,
|
||||||
|
style,
|
||||||
|
"use `std::ptr::eq` when comparing raw pointers"
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Operators {
|
pub struct Operators {
|
||||||
arithmetic_context: numeric_arithmetic::Context,
|
arithmetic_context: numeric_arithmetic::Context,
|
||||||
verbose_bit_mask_threshold: u64,
|
verbose_bit_mask_threshold: u64,
|
||||||
@ -699,6 +729,7 @@ pub struct Operators {
|
|||||||
MODULO_ONE,
|
MODULO_ONE,
|
||||||
MODULO_ARITHMETIC,
|
MODULO_ARITHMETIC,
|
||||||
NEEDLESS_BITWISE_BOOL,
|
NEEDLESS_BITWISE_BOOL,
|
||||||
|
PTR_EQ,
|
||||||
]);
|
]);
|
||||||
impl Operators {
|
impl Operators {
|
||||||
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
|
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
|
||||||
@ -722,6 +753,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
|||||||
erasing_op::check(cx, e, op.node, lhs, rhs);
|
erasing_op::check(cx, e, op.node, lhs, rhs);
|
||||||
identity_op::check(cx, e, op.node, lhs, rhs);
|
identity_op::check(cx, e, op.node, lhs, rhs);
|
||||||
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
|
needless_bitwise_bool::check(cx, e, op.node, lhs, rhs);
|
||||||
|
ptr_eq::check(cx, e, op.node, lhs, rhs);
|
||||||
}
|
}
|
||||||
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
|
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
|
||||||
bit_mask::check(cx, e, op.node, lhs, rhs);
|
bit_mask::check(cx, e, op.node, lhs, rhs);
|
||||||
|
65
clippy_lints/src/operators/ptr_eq.rs
Normal file
65
clippy_lints/src/operators/ptr_eq.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
|
use clippy_utils::source::snippet_opt;
|
||||||
|
use if_chain::if_chain;
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
|
||||||
|
use super::PTR_EQ;
|
||||||
|
|
||||||
|
static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
|
||||||
|
|
||||||
|
pub(super) fn check<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
expr: &'tcx Expr<'_>,
|
||||||
|
op: BinOpKind,
|
||||||
|
left: &'tcx Expr<'_>,
|
||||||
|
right: &'tcx Expr<'_>,
|
||||||
|
) {
|
||||||
|
if BinOpKind::Eq == op {
|
||||||
|
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
|
||||||
|
(Some(lhs), Some(rhs)) => (lhs, rhs),
|
||||||
|
_ => (left, right),
|
||||||
|
};
|
||||||
|
|
||||||
|
if_chain! {
|
||||||
|
if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left);
|
||||||
|
if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right);
|
||||||
|
if let Some(left_snip) = snippet_opt(cx, left_var.span);
|
||||||
|
if let Some(right_snip) = snippet_opt(cx, right_var.span);
|
||||||
|
then {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
PTR_EQ,
|
||||||
|
expr.span,
|
||||||
|
LINT_MSG,
|
||||||
|
"try",
|
||||||
|
format!("std::ptr::eq({}, {})", left_snip, right_snip),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the given expression is a cast to a usize, return the lhs of the cast
|
||||||
|
// E.g., `foo as *const _ as usize` returns `foo as *const _`.
|
||||||
|
fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
||||||
|
if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize {
|
||||||
|
if let ExprKind::Cast(expr, _) = cast_expr.kind {
|
||||||
|
return Some(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the given expression is a cast to a `*const` pointer, return the lhs of the cast
|
||||||
|
// E.g., `foo as *const _` returns `foo`.
|
||||||
|
fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
||||||
|
if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() {
|
||||||
|
if let ExprKind::Cast(expr, _) = cast_expr.kind {
|
||||||
|
return Some(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
@ -1,97 +0,0 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
|
||||||
use clippy_utils::source::snippet_opt;
|
|
||||||
use if_chain::if_chain;
|
|
||||||
use rustc_errors::Applicability;
|
|
||||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
|
||||||
/// ### What it does
|
|
||||||
/// Use `std::ptr::eq` when applicable
|
|
||||||
///
|
|
||||||
/// ### Why is this bad?
|
|
||||||
/// `ptr::eq` can be used to compare `&T` references
|
|
||||||
/// (which coerce to `*const T` implicitly) by their address rather than
|
|
||||||
/// comparing the values they point to.
|
|
||||||
///
|
|
||||||
/// ### Example
|
|
||||||
/// ```rust
|
|
||||||
/// let a = &[1, 2, 3];
|
|
||||||
/// let b = &[1, 2, 3];
|
|
||||||
///
|
|
||||||
/// assert!(a as *const _ as usize == b as *const _ as usize);
|
|
||||||
/// ```
|
|
||||||
/// Use instead:
|
|
||||||
/// ```rust
|
|
||||||
/// let a = &[1, 2, 3];
|
|
||||||
/// let b = &[1, 2, 3];
|
|
||||||
///
|
|
||||||
/// assert!(std::ptr::eq(a, b));
|
|
||||||
/// ```
|
|
||||||
#[clippy::version = "1.49.0"]
|
|
||||||
pub PTR_EQ,
|
|
||||||
style,
|
|
||||||
"use `std::ptr::eq` when comparing raw pointers"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint_pass!(PtrEq => [PTR_EQ]);
|
|
||||||
|
|
||||||
static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for PtrEq {
|
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|
||||||
if expr.span.from_expansion() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let ExprKind::Binary(ref op, left, right) = expr.kind {
|
|
||||||
if BinOpKind::Eq == op.node {
|
|
||||||
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
|
|
||||||
(Some(lhs), Some(rhs)) => (lhs, rhs),
|
|
||||||
_ => (left, right),
|
|
||||||
};
|
|
||||||
|
|
||||||
if_chain! {
|
|
||||||
if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left);
|
|
||||||
if let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right);
|
|
||||||
if let Some(left_snip) = snippet_opt(cx, left_var.span);
|
|
||||||
if let Some(right_snip) = snippet_opt(cx, right_var.span);
|
|
||||||
then {
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
PTR_EQ,
|
|
||||||
expr.span,
|
|
||||||
LINT_MSG,
|
|
||||||
"try",
|
|
||||||
format!("std::ptr::eq({}, {})", left_snip, right_snip),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the given expression is a cast to a usize, return the lhs of the cast
|
|
||||||
// E.g., `foo as *const _ as usize` returns `foo as *const _`.
|
|
||||||
fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
|
||||||
if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize {
|
|
||||||
if let ExprKind::Cast(expr, _) = cast_expr.kind {
|
|
||||||
return Some(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the given expression is a cast to a `*const` pointer, return the lhs of the cast
|
|
||||||
// E.g., `foo as *const _` returns `foo`.
|
|
||||||
fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
|
|
||||||
if cx.typeck_results().expr_ty(cast_expr).is_unsafe_ptr() {
|
|
||||||
if let ExprKind::Cast(expr, _) = cast_expr.kind {
|
|
||||||
return Some(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user