]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/modulo_arithmetic.rs
modify code
[rust.git] / clippy_lints / src / modulo_arithmetic.rs
index b24d5c1fc8ed15b27a30399c46514c575deacc14..d182a7d52497d45fd59cf8d367f8e84e207d3e10 100644 (file)
@@ -1,28 +1,30 @@
-use crate::consts::{constant, Constant};
-use crate::utils::{sext, span_lint_and_then};
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sext;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self};
+use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use std::fmt::Display;
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for modulo arithemtic.
+    /// ### What it does
+    /// Checks for modulo arithmetic.
     ///
-    /// **Why is this bad?** The results of modulo (%) operation might differ
+    /// ### Why is this bad?
+    /// The results of modulo (%) operation might differ
     /// depending on the language, when negative numbers are involved.
     /// If you interop with different languages it might be beneficial
     /// to double check all places that use modulo arithmetic.
     ///
     /// For example, in Rust `17 % -3 = 2`, but in Python `17 % -3 = -1`.
     ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
+    /// ### Example
     /// ```rust
     /// let x = -17 % 3;
     /// ```
+    #[clippy::version = "1.42.0"]
     pub MODULO_ARITHMETIC,
     restriction,
     "any modulo arithmetic statement"
@@ -36,9 +38,9 @@ struct OperandInfo {
     is_integral: bool,
 }
 
-fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<OperandInfo> {
-    match constant(cx, cx.tables, operand) {
-        Some((Constant::Int(v), _)) => match cx.tables.expr_ty(expr).kind {
+fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
+    match constant(cx, cx.typeck_results(), operand) {
+        Some((Constant::Int(v), _)) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
                 return Some(OperandInfo {
@@ -79,8 +81,8 @@ fn might_have_negative_value(t: &ty::TyS<'_>) -> bool {
     t.is_signed() || t.is_floating_point()
 }
 
-fn check_const_operands<'a, 'tcx>(
-    cx: &LateContext<'a, 'tcx>,
+fn check_const_operands<'tcx>(
+    cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
     lhs_operand: &OperandInfo,
     rhs_operand: &OperandInfo,
@@ -95,39 +97,39 @@ fn check_const_operands<'a, 'tcx>(
                 lhs_operand.string_representation.as_ref().unwrap(),
                 rhs_operand.string_representation.as_ref().unwrap()
             ),
-            |db| {
-                db.note("double check for expected result especially when interoperating with different languages");
+            |diag| {
+                diag.note("double check for expected result especially when interoperating with different languages");
                 if lhs_operand.is_integral {
-                    db.note("or consider using `rem_euclid` or similar function");
+                    diag.note("or consider using `rem_euclid` or similar function");
                 }
             },
         );
     }
 }
 
-fn check_non_const_operands<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, operand: &Expr<'_>) {
-    let operand_type = cx.tables.expr_ty(operand);
+fn check_non_const_operands<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, operand: &Expr<'_>) {
+    let operand_type = cx.typeck_results().expr_ty(operand);
     if might_have_negative_value(operand_type) {
         span_lint_and_then(
             cx,
             MODULO_ARITHMETIC,
             expr.span,
             "you are using modulo operator on types that might have different signs",
-            |db| {
-                db.note("double check for expected result especially when interoperating with different languages");
+            |diag| {
+                diag.note("double check for expected result especially when interoperating with different languages");
                 if operand_type.is_integral() {
-                    db.note("or consider using `rem_euclid` or similar function");
+                    diag.note("or consider using `rem_euclid` or similar function");
                 }
             },
         );
     }
 }
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ModuloArithmetic {
-    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
+impl<'tcx> LateLintPass<'tcx> for ModuloArithmetic {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         match &expr.kind {
             ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => {
-                if let BinOpKind::Rem = op.node {
+                if op.node == BinOpKind::Rem {
                     let lhs_operand = analyze_operand(lhs, cx, expr);
                     let rhs_operand = analyze_operand(rhs, cx, expr);
                     if_chain! {