@@ -21,7 +21,7 @@ use crate::utils::{get_item_name, get_parent_expr, implements_trait, in_constant
21
21
iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
22
22
span_lint_and_then, walk_ptrs_ty, SpanlessEq } ;
23
23
use crate :: utils:: sugg:: Sugg ;
24
- use crate :: syntax:: ast:: { LitKind , CRATE_NODE_ID } ;
24
+ use crate :: syntax:: ast:: LitKind ;
25
25
use crate :: consts:: { constant, Constant } ;
26
26
use crate :: rustc_errors:: Applicability ;
27
27
@@ -535,34 +535,39 @@ fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr, other: &Expr) {
535
535
return ;
536
536
}
537
537
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
+
538
549
span_lint_and_then (
539
550
cx,
540
551
CMP_OWNED ,
541
- expr . span ,
552
+ lint_span ,
542
553
"this creates an owned instance just for comparison" ,
543
554
|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 ;
562
559
}
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
+
564
569
db. span_suggestion_with_applicability (
565
- expr . span ,
570
+ lint_span ,
566
571
"try" ,
567
572
try_hint,
568
573
Applicability :: MachineApplicable , // snippet
0 commit comments