Skip to content

Make the filter_map lint more specific #3188

Closed
@ghost

Description

The intent of the filter_map method is to unwrap element values and skip Nones when iterating over elements that are Options. It's not a universal shorthand for filter followed by a call tomap. The filter_map documentation indicates this.

The current implementation of the fliter_map lint triggers on every call to filter followed by a call tomap and basically notes that the suggestion can make the code more complicated as a known issue. It encourages changes like this (from #3186):

extra_args
    .split("__CLIPPY_HACKERY__")
    .filter(|s| !s.is_empty())
    .map(str::to_owned)

to

extra_args
   .split("__CLIPPY_HACKERY__")
   .filter_map(|s| if s.is_empty() {
       None
   } else {
       Some(s.to_string())
   })

I find the final code is less readable and more complicated than the code at the start. Although, there is one less function call, there is now an if statement and extra code for constructing an option.

Let's change the lint to only trigger in the following conditions. In the table below option_expr is an expression with type Option<_> and result_expr is an expression with type Result<_, _>.

Code Suggestion
filter(|x| option_expr.is_some()).map(|x| x.unwrap()) filter_map(|x| option_expr)
filter(|x| option_expr.is_some()).flat_map(|x| x) filter_map(|x| option_expr)
filter(|x| result_expr.is_ok()).map(|x| x.unwrap()) filter_map(|x| result_expr.ok())

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