@@ -21,7 +21,7 @@ use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant
2121 iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
2222 span_lint_and_then, walk_ptrs_ty, SpanlessEq } ;
2323use crate :: utils:: sugg:: Sugg ;
24- use crate :: syntax:: ast:: { LitKind , CRATE_NODE_ID } ;
24+ use crate :: syntax:: ast:: LitKind ;
2525use crate :: consts:: { constant, Constant } ;
2626use crate :: rustc_errors:: Applicability ;
2727
@@ -535,34 +535,39 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
535535 return ;
536536 }
537537
538+ let other_gets_derefed = match other. node {
539+ ExprKind :: Unary ( UnDeref , _) => true ,
540+ _ => false ,
541+ } ;
542+
543+ let lint_span = if other_gets_derefed {
544+ expr. span . to ( other. span )
545+ } else {
546+ expr. span
547+ } ;
548+
538549 span_lint_and_then (
539550 cx,
540551 CMP_OWNED ,
541- expr . span ,
552+ lint_span ,
542553 "this creates an owned instance just for comparison" ,
543554 |db| {
544- // this is as good as our recursion check can get, we can't prove that the
545- // current function is
546- // called by
547- // PartialEq::eq, but we can at least ensure that this code is not part of it
548- let parent_fn = cx. tcx . hir . get_parent ( expr. id ) ;
549- let parent_impl = cx. tcx . hir . get_parent ( parent_fn) ;
550- if parent_impl != CRATE_NODE_ID {
551- if let Node :: Item ( item) = cx. tcx . hir . get ( parent_impl) {
552- if let ItemKind :: Impl ( .., Some ( ref trait_ref) , _, _) = item. node {
553- if trait_ref. path . def . def_id ( ) == partial_eq_trait_id {
554- // we are implementing PartialEq, don't suggest not doing `to_owned`, otherwise
555- // we go into
556- // recursion
557- db. span_label ( expr. span , "try calling implementing the comparison without allocating" ) ;
558- return ;
559- }
560- }
561- }
555+ // this also catches PartialEq implementations that call to_owned
556+ if other_gets_derefed {
557+ db. span_label ( lint_span, "try implementing the comparison without allocating" ) ;
558+ return ;
562559 }
563- let try_hint = if deref_arg_impl_partial_eq_other { format ! ( "*{}" , snip) } else { snip. to_string ( ) } ;
560+
561+ let try_hint = if deref_arg_impl_partial_eq_other {
562+ // suggest deref on the left
563+ format ! ( "*{}" , snip)
564+ } else {
565+ // suggest dropping the to_owned on the left
566+ snip. to_string ( )
567+ } ;
568+
564569 db. span_suggestion_with_applicability (
565- expr . span ,
570+ lint_span ,
566571 "try" ,
567572 try_hint,
568573 Applicability :: MachineApplicable , // snippet
0 commit comments