Skip to content

Make find_map lint be more conservative #4193

Closed
@yaahc

Description

@yaahc

The find_map lint will trigger if you do a filter followed by a map but its not always preferable.

---- dogfood stdout ----
status: exit code: 101
stdout:
stderr:     Blocking waiting for file lock on package cache lock
    Checking clippy v0.0.212 (/home/jlusby/git/rust/clippy)
error: called `find(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
   --> src/driver.rs:129:9
    |
129 | /         LINT_LEVELS
130 | |             .iter()
131 | |             .find(|level_mapping| level_mapping.0 == lint.group)
132 | |             .map(|(_, level)| level)
    | |____________________________________^
    |
    = note: `-D clippy::find-map` implied by `-D clippy::pedantic`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#find_map

error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead.
   --> src/driver.rs:205:24
    |
205 |               let desc = lints
    |  ________________________^
206 | |                 .iter()
207 | |                 .filter(|&lint| lint.group == group)
208 | |                 .map(|lint| lint.name)
    | |______________________________________^
    |
    = note: `-D clippy::filter-map` implied by `-D clippy::pedantic`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#filter_map

error: called `find(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead.
   --> src/driver.rs:129:9
    |
129 | /         LINT_LEVELS
130 | |             .iter()
131 | |             .find(|level_mapping| level_mapping.0 == lint.group)
132 | |             .map(|(_, level)| level)
    | |____________________________________^
    |
    = note: `-D clippy::find-map` implied by `-D clippy::pedantic`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#find_map

error: called `filter(p).map(q)` on an `Iterator`. This is more succinctly expressed by calling `.filter_map(..)` instead.
   --> src/driver.rs:205:24
    |
205 |               let desc = lints
    |  ________________________^
206 | |                 .iter()
207 | |                 .filter(|&lint| lint.group == group)
208 | |                 .map(|lint| lint.name)
    | |______________________________________^
    |
    = note: `-D clippy::filter-map` implied by `-D clippy::pedantic`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#filter_map

error: aborting due to 2 previous errors

In the case of the first lint at least, you'll run into lifetime issues if you try to replace lines 131 and 132 with a find_map call.

        LINT_LEVELS
            .iter()
            .find_map(|level_mapping| {
                if level_mapping.0 == lint.group {
                    Some(level_mapping.1)
                } else {
                    None
                }
            })
            .map(|level| match level {
                Level::Allow => "allow",
                Level::Warn => "warn",
                Level::Deny => "deny",
            })
            .unwrap()
master ✗ $ cargo check
    Checking clippy v0.0.212 (/home/jlusby/git/rust/clippy)
error[E0507]: cannot move out of `level_mapping.1` which is behind a shared reference
   --> src/driver.rs:133:26
    |
133 |                     Some(level_mapping.1)
    |                          ^^^^^^^^^^^^^^^ move occurs because `level_mapping.1` has type `lintlist::lint::Level`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0507`.
error: Could not compile `clippy`.

To learn more, run the command again with --verbose.

And even if it didn't run into the borrow error I personally feel like the find_map version is less concise than the filter -> map version.

If the Item type of the iterator was already a Try type then I can see it being easy enough to write a concise find_map impl, but with the boolean as the only starting point for the closure outputting Some or None I don't think it works as nicely as filter and map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-enhancementCategory: Enhancement of lints, like adding more cases or adding help messages

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions