54 lines
1.8 KiB
Rust
54 lines
1.8 KiB
Rust
use clippy_utils::ast_utils::is_useless_with_eq_exprs;
|
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
|
use clippy_utils::macros::{find_assert_eq_args, first_node_macro_backtrace};
|
|
use clippy_utils::{eq_expr_value, is_in_test_function};
|
|
use rustc_hir::{BinOpKind, Expr};
|
|
use rustc_lint::LateContext;
|
|
|
|
use super::EQ_OP;
|
|
|
|
pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
|
if let Some((macro_call, macro_name)) = first_node_macro_backtrace(cx, e).find_map(|macro_call| {
|
|
let name = cx.tcx.item_name(macro_call.def_id);
|
|
matches!(
|
|
name.as_str(),
|
|
"assert_eq" | "assert_ne" | "debug_assert_eq" | "debug_assert_ne"
|
|
)
|
|
.then(|| (macro_call, name))
|
|
}) && let Some((lhs, rhs, _)) = find_assert_eq_args(cx, e, macro_call.expn)
|
|
&& eq_expr_value(cx, lhs, rhs)
|
|
&& macro_call.is_local()
|
|
&& !is_in_test_function(cx.tcx, e.hir_id)
|
|
{
|
|
span_lint(
|
|
cx,
|
|
EQ_OP,
|
|
lhs.span.to(rhs.span),
|
|
&format!("identical args used in this `{macro_name}!` macro call"),
|
|
);
|
|
}
|
|
}
|
|
|
|
pub(crate) fn check<'tcx>(
|
|
cx: &LateContext<'tcx>,
|
|
e: &'tcx Expr<'_>,
|
|
op: BinOpKind,
|
|
left: &'tcx Expr<'_>,
|
|
right: &'tcx Expr<'_>,
|
|
) {
|
|
if is_useless_with_eq_exprs(op) && eq_expr_value(cx, left, right) && !is_in_test_function(cx.tcx, e.hir_id) {
|
|
span_lint_and_then(
|
|
cx,
|
|
EQ_OP,
|
|
e.span,
|
|
&format!("equal expressions as operands to `{}`", op.as_str()),
|
|
|diag| {
|
|
if let BinOpKind::Ne = op
|
|
&& cx.typeck_results().expr_ty(left).is_floating_point()
|
|
{
|
|
diag.note("if you intended to check if the operand is NaN, use `.is_nan()` instead");
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|