]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use crate::utils::span_lint_and_help; |
2 | use if_chain::if_chain; | |
3 | use rustc_hir as hir; | |
4 | use rustc_lint::{LateContext, LateLintPass}; | |
5 | use rustc_session::{declare_lint_pass, declare_tool_lint}; | |
6 | ||
7 | declare_clippy_lint! { | |
8 | /// **What it does:** Checks for division of integers | |
9 | /// | |
10 | /// **Why is this bad?** When outside of some very specific algorithms, | |
11 | /// integer division is very often a mistake because it discards the | |
12 | /// remainder. | |
13 | /// | |
14 | /// **Known problems:** None. | |
15 | /// | |
16 | /// **Example:** | |
17 | /// ```rust | |
18 | /// // Bad | |
19 | /// let x = 3 / 2; | |
20 | /// println!("{}", x); | |
21 | /// | |
22 | /// // Good | |
23 | /// let x = 3f32 / 2f32; | |
24 | /// println!("{}", x); | |
25 | /// ``` | |
26 | pub INTEGER_DIVISION, | |
27 | restriction, | |
28 | "integer division may cause loss of precision" | |
29 | } | |
30 | ||
31 | declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]); | |
32 | ||
33 | impl<'tcx> LateLintPass<'tcx> for IntegerDivision { | |
34 | fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { | |
35 | if is_integer_division(cx, expr) { | |
36 | span_lint_and_help( | |
37 | cx, | |
38 | INTEGER_DIVISION, | |
39 | expr.span, | |
40 | "integer division", | |
41 | None, | |
42 | "division of integers may cause loss of precision. consider using floats", | |
43 | ); | |
44 | } | |
45 | } | |
46 | } | |
47 | ||
48 | fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool { | |
49 | if_chain! { | |
50 | if let hir::ExprKind::Binary(binop, left, right) = &expr.kind; | |
51 | if let hir::BinOpKind::Div = &binop.node; | |
52 | then { | |
53 | let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); | |
54 | return left_ty.is_integral() && right_ty.is_integral(); | |
55 | } | |
56 | } | |
57 | ||
58 | false | |
59 | } |