From 993b4016db6684eeac1d5e9e986d18bd7f2fe1a3 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 9 May 2022 12:29:31 -0400 Subject: [PATCH] Don't lint `cmp_owned` when `From::from` results in a copy type. --- clippy_lints/src/misc.rs | 8 +++++-- tests/ui/cmp_owned/without_suggestion.rs | 22 ++++++++++++++++++++ tests/ui/cmp_owned/without_suggestion.stderr | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 18a98fc6f84..27a15b106fb 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::ty::implements_trait; +use clippy_utils::ty::{implements_trait, is_copy}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -584,7 +584,11 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: ExprKind::Call(path, [arg]) if path_def_id(cx, path) .and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM])) - .is_some() => + .map_or(false, |idx| match idx { + 0 => true, + 1 => !is_copy(cx, typeck.expr_ty(expr)), + _ => false, + }) => { (arg, arg.span) }, diff --git a/tests/ui/cmp_owned/without_suggestion.rs b/tests/ui/cmp_owned/without_suggestion.rs index f44a3901fb4..ae0862257eb 100644 --- a/tests/ui/cmp_owned/without_suggestion.rs +++ b/tests/ui/cmp_owned/without_suggestion.rs @@ -9,6 +9,10 @@ fn main() { let x = &&Baz; let y = &Baz; y.to_owned() == **x; + + let x = 0u32; + let y = U32Wrapper(x); + let _ = U32Wrapper::from(x) == y; } struct Foo; @@ -51,3 +55,21 @@ impl std::borrow::Borrow for Bar { &FOO } } + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct U32Wrapper(u32); +impl From for U32Wrapper { + fn from(x: u32) -> Self { + Self(x) + } +} +impl PartialEq for U32Wrapper { + fn eq(&self, other: &u32) -> bool { + self.0 == *other + } +} +impl PartialEq for u32 { + fn eq(&self, other: &U32Wrapper) -> bool { + *self == other.0 + } +} diff --git a/tests/ui/cmp_owned/without_suggestion.stderr b/tests/ui/cmp_owned/without_suggestion.stderr index 2ea3d8fac0d..d2dd14d8edb 100644 --- a/tests/ui/cmp_owned/without_suggestion.stderr +++ b/tests/ui/cmp_owned/without_suggestion.stderr @@ -13,7 +13,7 @@ LL | y.to_owned() == **x; | ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating error: this creates an owned instance just for comparison - --> $DIR/without_suggestion.rs:18:9 + --> $DIR/without_suggestion.rs:22:9 | LL | self.to_owned() == *other | ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating