@@ -4,12 +4,12 @@ use clippy_utils::{
4
4
ty:: implements_trait,
5
5
} ;
6
6
use rustc_errors:: Applicability ;
7
- use rustc_hir:: { def:: Res , Expr , ExprKind , ImplItem , ImplItemKind , ItemKind , LangItem , Node , PatKind , UnOp } ;
7
+ use rustc_hir:: { def:: Res , Expr , ExprKind , ImplItem , ImplItemKind , ItemKind , LangItem , Node , UnOp } ;
8
8
use rustc_hir_analysis:: hir_ty_to_ty;
9
9
use rustc_lint:: { LateContext , LateLintPass } ;
10
10
use rustc_middle:: ty:: EarlyBinder ;
11
11
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
12
- use rustc_span:: { sym, symbol} ;
12
+ use rustc_span:: { sym, symbol:: kw } ;
13
13
use std:: borrow:: Cow ;
14
14
15
15
declare_clippy_lint ! {
@@ -61,31 +61,39 @@ declare_clippy_lint! {
61
61
/// wrapping the result of `cmp` in `Some` for `partial_cmp`. Not doing this may silently
62
62
/// introduce an error upon refactoring.
63
63
///
64
+ /// ### Limitations
65
+ /// Will not lint if `Self` and `Rhs` do not have the same type.
66
+ ///
64
67
/// ### Example
65
- /// ```rust,ignore
68
+ /// ```rust
69
+ /// # use std::cmp::Ordering;
66
70
/// #[derive(Eq, PartialEq)]
67
71
/// struct A(u32);
68
72
///
69
73
/// impl Ord for A {
70
74
/// fn cmp(&self, other: &Self) -> Ordering {
71
- /// todo!();
75
+ /// // ...
76
+ /// # todo!();
72
77
/// }
73
78
/// }
74
79
///
75
80
/// impl PartialOrd for A {
76
81
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77
- /// todo!();
82
+ /// // ...
83
+ /// # todo!();
78
84
/// }
79
85
/// }
80
86
/// ```
81
87
/// Use instead:
82
- /// ```rust,ignore
88
+ /// ```rust
89
+ /// # use std::cmp::Ordering;
83
90
/// #[derive(Eq, PartialEq)]
84
91
/// struct A(u32);
85
92
///
86
93
/// impl Ord for A {
87
94
/// fn cmp(&self, other: &Self) -> Ordering {
88
- /// todo!();
95
+ /// // ...
96
+ /// # todo!();
89
97
/// }
90
98
/// }
91
99
///
@@ -105,8 +113,7 @@ declare_lint_pass!(IncorrectImpls => [INCORRECT_CLONE_IMPL_ON_COPY_TYPE, INCORRE
105
113
impl LateLintPass < ' _ > for IncorrectImpls {
106
114
#[ expect( clippy:: too_many_lines) ]
107
115
fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , impl_item : & ImplItem < ' _ > ) {
108
- let node = get_parent_node ( cx. tcx , impl_item. hir_id ( ) ) ;
109
- let Some ( Node :: Item ( item) ) = node else {
116
+ let Some ( Node :: Item ( item) ) = get_parent_node ( cx. tcx , impl_item. hir_id ( ) ) else {
110
117
return ;
111
118
} ;
112
119
let ItemKind :: Impl ( imp) = item. kind else {
@@ -115,7 +122,6 @@ impl LateLintPass<'_> for IncorrectImpls {
115
122
let Some ( trait_impl) = cx. tcx . impl_trait_ref ( item. owner_id ) . map ( EarlyBinder :: skip_binder) else {
116
123
return ;
117
124
} ;
118
- let trait_impl_def_id = trait_impl. def_id ;
119
125
if cx. tcx . is_automatically_derived ( item. owner_id . to_def_id ( ) ) {
120
126
return ;
121
127
}
@@ -127,7 +133,7 @@ impl LateLintPass<'_> for IncorrectImpls {
127
133
return ;
128
134
} ;
129
135
130
- if cx. tcx . is_diagnostic_item ( sym:: Clone , trait_impl_def_id )
136
+ if cx. tcx . is_diagnostic_item ( sym:: Clone , trait_impl . def_id )
131
137
&& let Some ( copy_def_id) = cx. tcx . get_diagnostic_item ( sym:: Copy )
132
138
&& implements_trait (
133
139
cx,
@@ -139,9 +145,9 @@ impl LateLintPass<'_> for IncorrectImpls {
139
145
if impl_item. ident . name == sym:: clone {
140
146
if block. stmts . is_empty ( )
141
147
&& let Some ( expr) = block. expr
142
- && let ExprKind :: Unary ( UnOp :: Deref , inner ) = expr. kind
143
- && let ExprKind :: Path ( qpath) = inner . kind
144
- && last_path_segment ( & qpath) . ident . name == symbol :: kw:: SelfLower
148
+ && let ExprKind :: Unary ( UnOp :: Deref , deref ) = expr. kind
149
+ && let ExprKind :: Path ( qpath) = deref . kind
150
+ && last_path_segment ( & qpath) . ident . name == kw:: SelfLower
145
151
{ } else {
146
152
span_lint_and_sugg (
147
153
cx,
@@ -163,7 +169,7 @@ impl LateLintPass<'_> for IncorrectImpls {
163
169
INCORRECT_CLONE_IMPL_ON_COPY_TYPE ,
164
170
impl_item. span ,
165
171
"incorrect implementation of `clone_from` on a `Copy` type" ,
166
- "remove this " ,
172
+ "remove it " ,
167
173
String :: new ( ) ,
168
174
Applicability :: MaybeIncorrect ,
169
175
) ;
@@ -172,7 +178,7 @@ impl LateLintPass<'_> for IncorrectImpls {
172
178
}
173
179
}
174
180
175
- if cx. tcx . is_diagnostic_item ( sym:: PartialOrd , trait_impl_def_id )
181
+ if cx. tcx . is_diagnostic_item ( sym:: PartialOrd , trait_impl . def_id )
176
182
&& impl_item. ident . name == sym:: partial_cmp
177
183
&& let Some ( ord_def_id) = cx
178
184
. tcx
@@ -203,10 +209,7 @@ impl LateLintPass<'_> for IncorrectImpls {
203
209
{ } else {
204
210
// If lhs and rhs are not the same type, bail. This makes creating a valid
205
211
// suggestion tons more complex.
206
- if let Some ( lhs) = trait_impl. substs . get ( 0 )
207
- && let Some ( rhs) = trait_impl. substs . get ( 1 )
208
- && lhs != rhs
209
- {
212
+ if let [ lhs, rhs, ..] = trait_impl. substs . as_slice ( ) && lhs != rhs {
210
213
return ;
211
214
}
212
215
@@ -216,22 +219,23 @@ impl LateLintPass<'_> for IncorrectImpls {
216
219
item. span ,
217
220
"incorrect implementation of `partial_cmp` on an `Ord` type" ,
218
221
|diag| {
219
- let ( help, app) = if let Some ( other) = body. params . get ( 1 )
220
- && let PatKind :: Binding ( _, _, other_ident, ..) = other. pat . kind
221
- {
222
- (
223
- Cow :: Owned ( format ! ( "{{ Some(self.cmp({})) }}" , other_ident. name) ) ,
224
- Applicability :: Unspecified ,
225
- )
222
+ let [ _, other] = body. params else {
223
+ return ;
224
+ } ;
225
+
226
+ let suggs = if let Some ( other_ident) = other. pat . simple_ident ( ) {
227
+ vec ! [ ( block. span, format!( "{{ Some(self.cmp({})) }}" , other_ident. name) ) ]
226
228
} else {
227
- ( Cow :: Borrowed ( "{ Some(self.cmp(...)) }" ) , Applicability :: HasPlaceholders )
229
+ vec ! [
230
+ ( block. span, "{ Some(self.cmp(other)) }" . to_owned( ) ) ,
231
+ ( other. pat. span, "other" . to_owned( ) ) ,
232
+ ]
228
233
} ;
229
234
230
- diag. span_suggestion (
231
- block. span ,
235
+ diag. multipart_suggestion (
232
236
"change this to" ,
233
- help ,
234
- app ,
237
+ suggs ,
238
+ Applicability :: Unspecified ,
235
239
) ;
236
240
}
237
241
) ;
0 commit comments