Skip to content

Commit bf2e631

Browse files
committed
Auto merge of #8807 - Jarcho:cmp_owned, r=giraffate
Fix `cmp_owned` on copy types fixes #8803 fixes #7365 changelog: Don't lint `cmp_owned` on `From::from` for copy types
2 parents d901079 + 993b401 commit bf2e631

File tree

3 files changed

+50
-26
lines changed

3 files changed

+50
-26
lines changed

clippy_lints/src/misc.rs

+27-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then};
22
use clippy_utils::source::{snippet, snippet_opt};
3-
use clippy_utils::ty::implements_trait;
3+
use clippy_utils::ty::{implements_trait, is_copy};
44
use if_chain::if_chain;
55
use rustc_ast::ast::LitKind;
66
use rustc_errors::Applicability;
@@ -20,8 +20,8 @@ use rustc_span::symbol::sym;
2020
use clippy_utils::consts::{constant, Constant};
2121
use clippy_utils::sugg::Sugg;
2222
use clippy_utils::{
23-
get_item_name, get_parent_expr, in_constant, is_diag_trait_item, is_integer_const, iter_input_pats,
24-
last_path_segment, match_any_def_paths, path_def_id, paths, unsext, SpanlessEq,
23+
get_item_name, get_parent_expr, in_constant, is_integer_const, iter_input_pats, last_path_segment,
24+
match_any_def_paths, path_def_id, paths, unsext, SpanlessEq,
2525
};
2626

2727
declare_clippy_lint! {
@@ -569,33 +569,34 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:
569569
})
570570
}
571571

572-
let (arg_ty, snip) = match expr.kind {
573-
ExprKind::MethodCall(.., args, _) if args.len() == 1 => {
574-
if_chain!(
575-
if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
576-
if is_diag_trait_item(cx, expr_def_id, sym::ToString)
577-
|| is_diag_trait_item(cx, expr_def_id, sym::ToOwned);
578-
then {
579-
(cx.typeck_results().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
580-
} else {
581-
return;
582-
}
583-
)
572+
let typeck = cx.typeck_results();
573+
let (arg, arg_span) = match expr.kind {
574+
ExprKind::MethodCall(.., [arg], _)
575+
if typeck
576+
.type_dependent_def_id(expr.hir_id)
577+
.and_then(|id| cx.tcx.trait_of_item(id))
578+
.map_or(false, |id| {
579+
matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))
580+
}) =>
581+
{
582+
(arg, arg.span)
584583
},
585-
ExprKind::Call(path, [arg]) => {
584+
ExprKind::Call(path, [arg])
586585
if path_def_id(cx, path)
587586
.and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM]))
588-
.is_some()
589-
{
590-
(cx.typeck_results().expr_ty(arg), snippet(cx, arg.span, ".."))
591-
} else {
592-
return;
593-
}
587+
.map_or(false, |idx| match idx {
588+
0 => true,
589+
1 => !is_copy(cx, typeck.expr_ty(expr)),
590+
_ => false,
591+
}) =>
592+
{
593+
(arg, arg.span)
594594
},
595595
_ => return,
596596
};
597597

598-
let other_ty = cx.typeck_results().expr_ty(other);
598+
let arg_ty = typeck.expr_ty(arg);
599+
let other_ty = typeck.expr_ty(other);
599600

600601
let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default();
601602
let with_deref = arg_ty
@@ -627,13 +628,14 @@ fn check_to_owned(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left:
627628
return;
628629
}
629630

631+
let arg_snip = snippet(cx, arg_span, "..");
630632
let expr_snip;
631633
let eq_impl;
632634
if with_deref.is_implemented() {
633-
expr_snip = format!("*{}", snip);
635+
expr_snip = format!("*{}", arg_snip);
634636
eq_impl = with_deref;
635637
} else {
636-
expr_snip = snip.to_string();
638+
expr_snip = arg_snip.to_string();
637639
eq_impl = without_deref;
638640
};
639641

tests/ui/cmp_owned/without_suggestion.rs

+22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ fn main() {
99
let x = &&Baz;
1010
let y = &Baz;
1111
y.to_owned() == **x;
12+
13+
let x = 0u32;
14+
let y = U32Wrapper(x);
15+
let _ = U32Wrapper::from(x) == y;
1216
}
1317

1418
struct Foo;
@@ -51,3 +55,21 @@ impl std::borrow::Borrow<Foo> for Bar {
5155
&FOO
5256
}
5357
}
58+
59+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
60+
struct U32Wrapper(u32);
61+
impl From<u32> for U32Wrapper {
62+
fn from(x: u32) -> Self {
63+
Self(x)
64+
}
65+
}
66+
impl PartialEq<u32> for U32Wrapper {
67+
fn eq(&self, other: &u32) -> bool {
68+
self.0 == *other
69+
}
70+
}
71+
impl PartialEq<U32Wrapper> for u32 {
72+
fn eq(&self, other: &U32Wrapper) -> bool {
73+
*self == other.0
74+
}
75+
}

tests/ui/cmp_owned/without_suggestion.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | y.to_owned() == **x;
1313
| ^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating
1414

1515
error: this creates an owned instance just for comparison
16-
--> $DIR/without_suggestion.rs:18:9
16+
--> $DIR/without_suggestion.rs:22:9
1717
|
1818
LL | self.to_owned() == *other
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^ try implementing the comparison without allocating

0 commit comments

Comments
 (0)