Skip to content

filter_map_identity is arguably overzealous #9377

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
scottmcm opened this issue Aug 25, 2022 · 1 comment
Open

filter_map_identity is arguably overzealous #9377

scottmcm opened this issue Aug 25, 2022 · 1 comment
Labels
I-false-positive Issue: The lint was triggered on code it shouldn't have

Comments

@scottmcm
Copy link
Member

scottmcm commented Aug 25, 2022

Description

lint: https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_identity

This was originally added as being like flat_map_identity (#6685), but they're not quite analogous. .flatten() is unambiguously better than .flat_map(identity), but the same isn't true for .filter_map(identity).

The problem is that (as I recently mentioned in rust-lang/rust#99230 (comment)), FlatMap (including Flatten) is a fundamentally harder problem than FilterMap, because it needs to deal in iterators that might have more than one item. And thus, for example,

let flatten_it = a.iter().copied().flatten();
let filter_map_it = a.iter().copied().filter_map(|x| x);
dbg!([size_of_val(&flatten_it), size_of_val(&filter_map_it)]); // 32, 16
dbg!([flatten_it.size_hint(), filter_map_it.size_hint()]); // (0, None), (0, Some(3))

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f1ccc42f95540d435e6d7caa58d29ed8

So perhaps this shouldn't be warn-by-default when it would also be plausible to have a performance-category lint to say to do exactly the opposite.

Version

(Not really version-specific; inherent to the definition of the lint.)

Additional Labels

@rustbot label +I-false-positive

@rustbot rustbot added the I-false-positive Issue: The lint was triggered on code it shouldn't have label Aug 25, 2022
cuviper added a commit to cuviper/rust that referenced this issue Feb 16, 2024
For iterators like `Once` and `option::IntoIter` that only ever have a
single item at most, the front and back iterator states in `FlatMap` and
`Flatten` are a waste, as they're always consumed already. We can use
specialization for these types to simplify the iterator methods.

It's a somewhat common pattern to use `flatten()` for options and
results, even recommended by [multiple][1] [clippy][2] [lints][3]. The
implementation is more efficient with `filter_map`, as mentioned in
[clippy#9377], but this new specialization should close some of that
gap for existing code that flattens.

[1]: https://rust-lang.github.io/rust-clippy/master/#filter_map_identity
[2]: https://rust-lang.github.io/rust-clippy/master/#option_filter_map
[3]: https://rust-lang.github.io/rust-clippy/master/#result_filter_map
[clippy#9377]: rust-lang/rust-clippy#9377
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 16, 2024
Specialize flattening iterators with only one inner item

For iterators like `Once` and `option::IntoIter` that only ever have a
single item at most, the front and back iterator states in `FlatMap` and
`Flatten` are a waste, as they're always consumed already. We can use
specialization for these types to simplify the iterator methods.

It's a somewhat common pattern to use `flatten()` for options and
results, even recommended by [multiple][1] [clippy][2] [lints][3]. The
implementation is more efficient with `filter_map`, as mentioned in
[clippy#9377], but this new specialization should close some of that
gap for existing code that flattens.

[1]: https://rust-lang.github.io/rust-clippy/master/#filter_map_identity
[2]: https://rust-lang.github.io/rust-clippy/master/#option_filter_map
[3]: https://rust-lang.github.io/rust-clippy/master/#result_filter_map
[clippy#9377]: rust-lang/rust-clippy#9377
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 17, 2024
Specialize flattening iterators with only one inner item

For iterators like `Once` and `option::IntoIter` that only ever have a
single item at most, the front and back iterator states in `FlatMap` and
`Flatten` are a waste, as they're always consumed already. We can use
specialization for these types to simplify the iterator methods.

It's a somewhat common pattern to use `flatten()` for options and
results, even recommended by [multiple][1] [clippy][2] [lints][3]. The
implementation is more efficient with `filter_map`, as mentioned in
[clippy#9377], but this new specialization should close some of that
gap for existing code that flattens.

[1]: https://rust-lang.github.io/rust-clippy/master/#filter_map_identity
[2]: https://rust-lang.github.io/rust-clippy/master/#option_filter_map
[3]: https://rust-lang.github.io/rust-clippy/master/#result_filter_map
[clippy#9377]: rust-lang/rust-clippy#9377
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Feb 18, 2024
Specialize flattening iterators with only one inner item

For iterators like `Once` and `option::IntoIter` that only ever have a
single item at most, the front and back iterator states in `FlatMap` and
`Flatten` are a waste, as they're always consumed already. We can use
specialization for these types to simplify the iterator methods.

It's a somewhat common pattern to use `flatten()` for options and
results, even recommended by [multiple][1] [clippy][2] [lints][3]. The
implementation is more efficient with `filter_map`, as mentioned in
[clippy#9377], but this new specialization should close some of that
gap for existing code that flattens.

[1]: https://rust-lang.github.io/rust-clippy/master/#filter_map_identity
[2]: https://rust-lang.github.io/rust-clippy/master/#option_filter_map
[3]: https://rust-lang.github.io/rust-clippy/master/#result_filter_map
[clippy#9377]: rust-lang/rust-clippy#9377
@cuviper
Copy link
Member

cuviper commented Feb 18, 2024

FWIW, nightly flatten now fares a little better in that example. The size_of difference is still there, but it uses a specialized implementation, including a size hint as good as filter_map's.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
I-false-positive Issue: The lint was triggered on code it shouldn't have
Projects
None yet
Development

No branches or pull requests

3 participants