From fff9a8ea9c56d5075c23d9d5b2d8b0838eee0da3 Mon Sep 17 00:00:00 2001 From: Tim Bodeit Date: Sat, 23 Nov 2019 22:35:21 +0100 Subject: [PATCH] [comparison_chain] #4827 Check `core::cmp::Ord` is implemented Only emit lint, if `cmp` is actually available on the type being compared. Don't emit lint in cases where only `PartialOrd` is implemented. --- clippy_lints/src/comparison_chain.rs | 12 +++++- tests/ui/comparison_chain.rs | 61 ++++++++++++++++++++++++++++ tests/ui/comparison_chain.stderr | 42 ++++++++++++++++++- 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 6968d8f65599..087bceaffd98 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -1,4 +1,6 @@ -use crate::utils::{if_sequence, parent_node_is_if_expr, span_help_and_lint, SpanlessEq}; +use crate::utils::{ + get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_help_and_lint, SpanlessEq, +}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; @@ -84,6 +86,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ComparisonChain { { return; } + + // Check that the type being compared implements `core::cmp::Ord` + let ty = cx.tables.expr_ty(lhs1); + let is_ord = get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])); + + if !is_ord { + return; + } } else { // We only care about comparison chains return; diff --git a/tests/ui/comparison_chain.rs b/tests/ui/comparison_chain.rs index b697413b6e03..9c2128469de9 100644 --- a/tests/ui/comparison_chain.rs +++ b/tests/ui/comparison_chain.rs @@ -76,4 +76,65 @@ fn f(x: u8, y: u8, z: u8) { } } +#[allow(clippy::float_cmp)] +fn g(x: f64, y: f64, z: f64) { + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if x < y { + b() + } + + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if x < y { + b() + } else { + c() + } + + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if y > x { + b() + } else { + c() + } + + // Ignored: f64 doesn't implement Ord + if x > 1.0 { + a() + } else if x < 1.0 { + b() + } else if x == 1.0 { + c() + } +} + +fn h(x: T, y: T, z: T) { + if x > y { + a() + } else if x < y { + b() + } + + if x > y { + a() + } else if x < y { + b() + } else { + c() + } + + if x > y { + a() + } else if y > x { + b() + } else { + c() + } +} + fn main() {} diff --git a/tests/ui/comparison_chain.stderr b/tests/ui/comparison_chain.stderr index 575181dd7194..69db88b03b5b 100644 --- a/tests/ui/comparison_chain.stderr +++ b/tests/ui/comparison_chain.stderr @@ -53,5 +53,45 @@ LL | | } | = help: Consider rewriting the `if` chain to use `cmp` and `match`. -error: aborting due to 4 previous errors +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:117:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if x < y { +LL | | b() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:123:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if x < y { +LL | | b() +LL | | } else { +LL | | c() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:131:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if y > x { +LL | | b() +LL | | } else { +LL | | c() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: aborting due to 7 previous errors