@@ -18,15 +18,25 @@ declare_clippy_lint! {
1818 /// possible) than to use `Vec::sort_by` and and a more complicated
1919 /// closure.
2020 ///
21- /// **Known problems:** None.
21+ /// **Known problems:**
22+ /// If the suggested `Vec::sort_by_key` uses Reverse and it isn't
23+ /// imported by a use statement in the current frame, then a `use`
24+ /// statement that imports it will need to be added (which this lint
25+ /// can't do).
2226 ///
2327 /// **Example:**
2428 ///
2529 /// ```rust
26- /// vec.sort_by(|a, b| a.foo().cmp(b.foo()));
30+ /// # struct A;
31+ /// # impl A { fn foo(&self) {} }
32+ /// # let mut vec: Vec<A> = Vec::new();
33+ /// vec.sort_by(|a, b| a.foo().cmp(&b.foo()));
2734 /// ```
2835 /// Use instead:
2936 /// ```rust
37+ /// # struct A;
38+ /// # impl A { fn foo(&self) {} }
39+ /// # let mut vec: Vec<A> = Vec::new();
3040 /// vec.sort_by_key(|a| a.foo());
3141 /// ```
3242 pub UNNECESSARY_SORT_BY ,
@@ -50,6 +60,7 @@ struct SortByKeyDetection {
5060 vec_name : String ,
5161 closure_arg : String ,
5262 closure_body : String ,
63+ reverse : bool ,
5364 unstable : bool ,
5465}
5566
@@ -172,16 +183,16 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
172183 if let ExprKind :: MethodCall ( method_path, _, [ ref left_expr, ref right_expr] ) = & closure_body. value. kind;
173184 if method_path. ident. name. to_ident_string( ) == "cmp" ;
174185 then {
175- let ( closure_body, closure_arg) = if mirrored_exprs(
186+ let ( closure_body, closure_arg, reverse ) = if mirrored_exprs(
176187 & cx,
177188 & left_expr,
178189 & left_ident,
179190 & right_expr,
180191 & right_ident
181192 ) {
182- ( Sugg :: hir( cx, & left_expr, ".." ) . to_string( ) , left_ident. name. to_string( ) )
193+ ( Sugg :: hir( cx, & left_expr, ".." ) . to_string( ) , left_ident. name. to_string( ) , false )
183194 } else if mirrored_exprs( & cx, & left_expr, & right_ident, & right_expr, & left_ident) {
184- ( format! ( "Reverse({})" , Sugg :: hir( cx, & left_expr, ".." ) . to_string( ) ) , right_ident. name. to_string( ) )
195+ ( Sugg :: hir( cx, & left_expr, ".." ) . to_string( ) , right_ident. name. to_string( ) , true )
185196 } else {
186197 return None ;
187198 } ;
@@ -196,7 +207,13 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
196207 Some ( LintTrigger :: Sort ( SortDetection { vec_name, unstable } ) )
197208 }
198209 else {
199- Some ( LintTrigger :: SortByKey ( SortByKeyDetection { vec_name, unstable, closure_arg, closure_body } ) )
210+ Some ( LintTrigger :: SortByKey ( SortByKeyDetection {
211+ vec_name,
212+ unstable,
213+ closure_arg,
214+ closure_body,
215+ reverse
216+ } ) )
200217 }
201218 }
202219 } else {
@@ -219,9 +236,17 @@ impl LateLintPass<'_, '_> for UnnecessarySortBy {
219236 trigger. vec_name,
220237 if trigger. unstable { "_unstable" } else { "" } ,
221238 trigger. closure_arg,
222- trigger. closure_body,
239+ if trigger. reverse {
240+ format!( "Reverse({})" , trigger. closure_body)
241+ } else {
242+ trigger. closure_body. to_string( )
243+ } ,
223244 ) ,
224- Applicability :: MachineApplicable ,
245+ if trigger. reverse {
246+ Applicability :: MaybeIncorrect
247+ } else {
248+ Applicability :: MachineApplicable
249+ } ,
225250 ) ,
226251 Some ( LintTrigger :: Sort ( trigger) ) => utils:: span_lint_and_sugg (
227252 cx,
0 commit comments