Rust-clippy: Incorrect suggestion in "unnecessary-sort-by"

Created on 2 Sep 2020  路  5Comments  路  Source: rust-lang/rust-clippy

This code triggers the following suggestion:

error: use Vec::sort_by_key here instead
   --> src/report/mod.rs:223:5
    |
223 |     crates.sort_unstable_by(|a, b| a.id().cmp(&b.id()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crates.sort_unstable_by_key(|&a| a.id())`
    |
    = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by

However, the suggested code does not work: &a is rejected as a pattern, it says I "cannot move out of a shared reference". using just a for the closure argument works.

Most helpful comment

I will work on this one

All 5 comments

I will work on this one

Restrict unnecessary_sort_by to non-reference, Copy types

Hm, that's not really a fix, is it? The lint was very useful here and helped improve the code. Just the auto-suggestions was wrong.

The problem is that the lint suggests using Reverse where applicable

pub struct Reverse<T>(pub T);

For example in this case:

    // Reverse examples
    vec.sort_by(|a, b| b.cmp(a));

The suggestion ends up being:

    vec.sort_by_key(|b| Reverse(b));

If we don't destructure the referenced type, we hit https://github.com/rust-lang/rust/issues/34162

error: lifetime may not live long enough
  --> /home/ebroto/src/ebroto-clippy/tests/ui/unnecessary_sort_by.fixed:19:25
   |
19 |     vec.sort_by_key(|b| Reverse(b));
   |                      -- ^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                      ||
   |                      |return type of closure is Reverse<&'2 isize>
   |                      has type `&'1 isize`

error: aborting due to previous error

But after giving this a bit more thought I agree and this is too restrictive, we should be able to identify when the argument to Reverse is a reference.

I will give this another shot.

Or maybe if the situation is too complicated (references / non-Copy types) it could not to the Reverse thing, but still detect cmp like before to suggest the by_key? That seems like it is unrelated in principle, though I know little about how clippy detects these things.

I ran in to failure with the suggestion applied to snapshots.sort_unstable_by(|a, b| b.datetime().cmp(&a.datetime())) where a and b are borrowed. I didn't know about Reverse :)

If we don't destructure the referenced type, we hit rust-lang/rust#34162

In my case I'm just taking the reference and giving Reverse an owned Copy type... DateTime, so it works fine snapshots.sort_unstable_by_key(|b| Reverse(b.datetime())).

Thank you for working on this. This is a great clippy.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

choleraehyq picture choleraehyq  路  21Comments

Manishearth picture Manishearth  路  18Comments

Manishearth picture Manishearth  路  26Comments

kevincox picture kevincox  路  17Comments

Shnatsel picture Shnatsel  路  23Comments