|
1 | 1 | use crate::consts::{constant_simple, Constant};
|
2 |
| -use rustc::lint::*; |
| 2 | +use crate::utils::{match_def_path, opt_def_id, paths, sext, span_lint}; |
3 | 3 | use rustc::hir::*;
|
| 4 | +use rustc::lint::*; |
| 5 | +use rustc::ty::{self, TyCtxt}; |
4 | 6 | use std::cmp::{Ordering, PartialOrd};
|
5 |
| -use crate::utils::{match_def_path, opt_def_id, paths, span_lint}; |
6 | 7 |
|
7 | 8 | /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are
|
8 | 9 | /// used to clamp values, but switched so that the result is constant.
|
@@ -36,21 +37,43 @@ impl LintPass for MinMaxPass {
|
36 | 37 | impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass {
|
37 | 38 | fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
38 | 39 | if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) {
|
39 |
| - if let Some((inner_max, inner_c, _)) = min_max(cx, oe) { |
| 40 | + if let Some((inner_max, inner_c, ie)) = min_max(cx, oe) { |
40 | 41 | if outer_max == inner_max {
|
41 | 42 | return;
|
42 | 43 | }
|
43 |
| - match (outer_max, outer_c.partial_cmp(&inner_c)) { |
| 44 | + match ( |
| 45 | + outer_max, |
| 46 | + const_partial_cmp(cx.tcx, &outer_c, &inner_c, &cx.tables.expr_ty(ie).sty), |
| 47 | + ) { |
44 | 48 | (_, None) | (MinMax::Max, Some(Ordering::Less)) | (MinMax::Min, Some(Ordering::Greater)) => (),
|
45 | 49 | _ => {
|
46 |
| - span_lint(cx, MIN_MAX, expr.span, "this min/max combination leads to constant result"); |
| 50 | + span_lint( |
| 51 | + cx, |
| 52 | + MIN_MAX, |
| 53 | + expr.span, |
| 54 | + "this min/max combination leads to constant result", |
| 55 | + ); |
47 | 56 | },
|
48 | 57 | }
|
49 | 58 | }
|
50 | 59 | }
|
51 | 60 | }
|
52 | 61 | }
|
53 | 62 |
|
| 63 | +// Constant::partial_cmp incorrectly orders signed integers |
| 64 | +fn const_partial_cmp(tcx: TyCtxt, a: &Constant, b: &Constant, expr_ty: &ty::TypeVariants) -> Option<Ordering> { |
| 65 | + match *expr_ty { |
| 66 | + ty::TyInt(int_ty) => { |
| 67 | + if let (&Constant::Int(a), &Constant::Int(b)) = (a, b) { |
| 68 | + Some(sext(tcx, a, int_ty).cmp(&sext(tcx, b, int_ty))) |
| 69 | + } else { |
| 70 | + None |
| 71 | + } |
| 72 | + }, |
| 73 | + _ => a.partial_cmp(&b), |
| 74 | + } |
| 75 | +} |
| 76 | + |
54 | 77 | #[derive(PartialEq, Eq, Debug)]
|
55 | 78 | enum MinMax {
|
56 | 79 | Min,
|
|
0 commit comments