manual_rem_euclid
: Check HIR tree first.
This commit is contained in:
parent
44f87e8cc1
commit
0f4cd13f66
@ -48,35 +48,30 @@ pub fn new(msrv: Msrv) -> Self {
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
|
impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
if !self.msrv.meets(msrvs::REM_EUCLID) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::REM_EUCLID_CONST) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if in_external_macro(cx.sess(), expr.span) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (x % c + c) % c
|
// (x % c + c) % c
|
||||||
if let ExprKind::Binary(op1, expr1, right) = expr.kind
|
if let ExprKind::Binary(rem_op, rem_lhs, rem_rhs) = expr.kind
|
||||||
&& op1.node == BinOpKind::Rem
|
&& rem_op.node == BinOpKind::Rem
|
||||||
|
&& let ExprKind::Binary(add_op, add_lhs, add_rhs) = rem_lhs.kind
|
||||||
|
&& add_op.node == BinOpKind::Add
|
||||||
&& let ctxt = expr.span.ctxt()
|
&& let ctxt = expr.span.ctxt()
|
||||||
&& expr1.span.ctxt() == ctxt
|
&& rem_lhs.span.ctxt() == ctxt
|
||||||
&& let Some(const1) = check_for_unsigned_int_constant(cx, right)
|
&& rem_rhs.span.ctxt() == ctxt
|
||||||
&& let ExprKind::Binary(op2, left, right) = expr1.kind
|
&& add_lhs.span.ctxt() == ctxt
|
||||||
&& op2.node == BinOpKind::Add
|
&& add_rhs.span.ctxt() == ctxt
|
||||||
&& let Some((const2, expr2)) = check_for_either_unsigned_int_constant(cx, left, right)
|
&& !in_external_macro(cx.sess(), expr.span)
|
||||||
&& expr2.span.ctxt() == ctxt
|
&& self.msrv.meets(msrvs::REM_EUCLID)
|
||||||
&& let ExprKind::Binary(op3, expr3, right) = expr2.kind
|
&& (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !in_constant(cx, expr.hir_id))
|
||||||
&& op3.node == BinOpKind::Rem
|
&& let Some(const1) = check_for_unsigned_int_constant(cx, rem_rhs)
|
||||||
&& let Some(const3) = check_for_unsigned_int_constant(cx, right)
|
&& let Some((const2, add_other)) = check_for_either_unsigned_int_constant(cx, add_lhs, add_rhs)
|
||||||
|
&& let ExprKind::Binary(rem2_op, rem2_lhs, rem2_rhs) = add_other.kind
|
||||||
|
&& rem2_op.node == BinOpKind::Rem
|
||||||
|
&& const1 == const2
|
||||||
|
&& let Some(hir_id) = path_to_local(rem2_lhs)
|
||||||
|
&& let Some(const3) = check_for_unsigned_int_constant(cx, rem2_rhs)
|
||||||
// Also ensures the const is nonzero since zero can't be a divisor
|
// Also ensures the const is nonzero since zero can't be a divisor
|
||||||
&& const1 == const2 && const2 == const3
|
&& const2 == const3
|
||||||
&& let Some(hir_id) = path_to_local(expr3)
|
&& rem2_lhs.span.ctxt() == ctxt
|
||||||
&& let Node::Pat(_) = cx.tcx.hir_node(hir_id)
|
&& rem2_rhs.span.ctxt() == ctxt
|
||||||
{
|
{
|
||||||
// Apply only to params or locals with annotated types
|
// Apply only to params or locals with annotated types
|
||||||
match cx.tcx.parent_hir_node(hir_id) {
|
match cx.tcx.parent_hir_node(hir_id) {
|
||||||
@ -91,7 +86,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let rem_of = snippet_with_context(cx, expr3.span, ctxt, "_", &mut app).0;
|
let rem_of = snippet_with_context(cx, rem2_lhs.span, ctxt, "_", &mut app).0;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
MANUAL_REM_EUCLID,
|
MANUAL_REM_EUCLID,
|
||||||
|
Loading…
Reference in New Issue
Block a user