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 {
|
||||
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
|
||||
if let ExprKind::Binary(op1, expr1, right) = expr.kind
|
||||
&& op1.node == BinOpKind::Rem
|
||||
if let ExprKind::Binary(rem_op, rem_lhs, rem_rhs) = expr.kind
|
||||
&& 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()
|
||||
&& expr1.span.ctxt() == ctxt
|
||||
&& let Some(const1) = check_for_unsigned_int_constant(cx, right)
|
||||
&& let ExprKind::Binary(op2, left, right) = expr1.kind
|
||||
&& op2.node == BinOpKind::Add
|
||||
&& let Some((const2, expr2)) = check_for_either_unsigned_int_constant(cx, left, right)
|
||||
&& expr2.span.ctxt() == ctxt
|
||||
&& let ExprKind::Binary(op3, expr3, right) = expr2.kind
|
||||
&& op3.node == BinOpKind::Rem
|
||||
&& let Some(const3) = check_for_unsigned_int_constant(cx, right)
|
||||
&& rem_lhs.span.ctxt() == ctxt
|
||||
&& rem_rhs.span.ctxt() == ctxt
|
||||
&& add_lhs.span.ctxt() == ctxt
|
||||
&& add_rhs.span.ctxt() == ctxt
|
||||
&& !in_external_macro(cx.sess(), expr.span)
|
||||
&& self.msrv.meets(msrvs::REM_EUCLID)
|
||||
&& (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !in_constant(cx, expr.hir_id))
|
||||
&& let Some(const1) = check_for_unsigned_int_constant(cx, rem_rhs)
|
||||
&& 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
|
||||
&& const1 == const2 && const2 == const3
|
||||
&& let Some(hir_id) = path_to_local(expr3)
|
||||
&& let Node::Pat(_) = cx.tcx.hir_node(hir_id)
|
||||
&& const2 == const3
|
||||
&& rem2_lhs.span.ctxt() == ctxt
|
||||
&& rem2_rhs.span.ctxt() == ctxt
|
||||
{
|
||||
// Apply only to params or locals with annotated types
|
||||
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 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(
|
||||
cx,
|
||||
MANUAL_REM_EUCLID,
|
||||
|
Loading…
Reference in New Issue
Block a user