Repository: rust
Issue: rustc shouldn't suggest returning `Option<&Option<T>>` in `filter_map`
Labels: A-diagnostics,T-compiler

### Code

```Rust
struct NonCopy;

fn main() {
    _ = vec![Some(()), None, Some(())].iter().filter_map(|x| x);
    _ = vec![Some(NonCopy), None, Some(NonCopy)].iter().filter_map(|x| x);
    _ = vec![Some(()), None, Some(())].iter_mut().filter_map(|x| x);
    _ = vec![Some(NonCopy), None, Some(NonCopy)].iter_mut().filter_map(|x| x);
}
```


### Current output

```Shell
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:4:62
  |
4 |     _ = vec![Some(()), None, Some(())].iter().filter_map(|x| x);
  |                                                              ^ expected `Option<_>`, found `&Option<()>`
  |
  = note:   expected enum `Option<_>`
          found reference `&Option<()>`
help: try wrapping the expression in `Some`
  |
4 |     _ = vec![Some(()), None, Some(())].iter().filter_map(|x| Some(x));
  |                                                              +++++ +

error[E0308]: mismatched types
 --> src/main.rs:5:72
  |
5 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter().filter_map(|x| x);
  |                                                                        ^ expected `Option<_>`, found `&Option<NonCopy>`
  |
  = note:   expected enum `Option<_>`
          found reference `&Option<NonCopy>`
help: try wrapping the expression in `Some`
  |
5 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter().filter_map(|x| Some(x));
  |                                                                        +++++ +

error[E0308]: mismatched types
 --> src/main.rs:6:66
  |
6 |     _ = vec![Some(()), None, Some(())].iter_mut().filter_map(|x| x);
  |                                                                  ^ expected `Option<_>`, found `&mut Option<()>`
  |
  = note:           expected enum `Option<_>`
          found mutable reference `&mut Option<()>`
help: try wrapping the expression in `Some`
  |
6 |     _ = vec![Some(()), None, Some(())].iter_mut().filter_map(|x| Some(x));
  |                                                                  +++++ +

error[E0308]: mismatched types
 --> src/main.rs:7:76
  |
7 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter_mut().filter_map(|x| x);
  |                                                                            ^ expected `Option<_>`, found `&mut Option<NonCopy>`
  |
  = note:           expected enum `Option<_>`
          found mutable reference `&mut Option<NonCopy>`
help: try wrapping the expression in `Some`
  |
7 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter_mut().filter_map(|x| Some(x));
  |                                                                            +++++ +

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 4 previous errors
```


### Desired output

```Shell
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:4:62
  |
4 |     _ = vec![Some(()), None, Some(())].iter().filter_map(|x| x);
  |                                                              ^ expected `Option<_>`, found `&Option<()>`
  |
  = note:   expected enum `Option<_>`
          found reference `&Option<()>`
help: try dereferencing `x`
  |
4 |     _ = vec![Some(()), None, Some(())].iter().filter_map(|&x| x); // or *x
  |                                                           +

error[E0308]: mismatched types
 --> src/main.rs:5:72
  |
5 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter().filter_map(|x| x);
  |                                                                        ^ expected `Option<_>`, found `&Option<NonCopy>`
  |
  = note:   expected enum `Option<_>`
          found reference `&Option<NonCopy>`
help: try calling `.as_ref()` on `x`
  |
5 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter().filter_map(|x| x.as_ref());
  |                                                                         +++++++++

error[E0308]: mismatched types
 --> src/main.rs:6:66
  |
6 |     _ = vec![Some(()), None, Some(())].iter_mut().filter_map(|x| x);
  |                                                                  ^ expected `Option<_>`, found `&mut Option<()>`
  |
  = note:           expected enum `Option<_>`
          found mutable reference `&mut Option<()>`
help: try dereferencing `x`
  |
6 |     _ = vec![Some(()), None, Some(())].iter_mut().filter_map(|&mut x| x); // or *x
  |                                                               ++++

error[E0308]: mismatched types
 --> src/main.rs:7:76
  |
7 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter_mut().filter_map(|x| x);
  |                                                                            ^ expected `Option<_>`, found `&mut Option<NonCopy>`
  |
  = note:           expected enum `Option<_>`
          found mutable reference `&mut Option<NonCopy>`
help: try calling `.as_mut()` on `x`
  |
7 |     _ = vec![Some(NonCopy), None, Some(NonCopy)].iter_mut().filter_map(|x| x.as_mut());
  |                                                                             +++++++++

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` (bin "playground") due to 4 previous errors
```


### Rationale and extra context

`Some(x)` is useless in `filter_map`, and is equivalent to `map(|x| x)` (which is equivalent to no mapping at all). We shouldn't suggest this at all really, but it's good enough for the general case - but with `&Option<T>`, we should really be able to tell they want to filter by this option instead.

This could be caused by changing `into_iter` to `iter`, as you then have `&Option<T>`. The user could write this using `flatten` instead but they're not guided in that (correct) direction - if this change is made, clippy will then suggest `flatten` (rust-lang/rust-clippy#12501)

### Other cases

_No response_

### Rust Version

```Shell
rustc 1.78.0-nightly (766bdce74 2024-03-16)
binary: rustc
commit-hash: 766bdce744d531267d53ba2a3f9ffcda69fb9b17
commit-date: 2024-03-16
host: x86_64-pc-windows-msvc
release: 1.78.0-nightly
LLVM version: 18.1.2
```


### Anything else?

We could limit this to only `|x| x` instead of something like `|(x, y)| if true { x } else { y }`. Both of these should work, although the second case isn't relevant to `flatten`, but it should still make sense?

Considering how general this error message is (`suggest_compatible_variants`), I think we could probably generalize this further, instead of only suggesting this in `filter_map`.