Repository: rust
Issue: compiler suggestions lead to more buggy code
Labels: A-diagnostics,A-closures,T-compiler,C-bug,A-suggestion-diagnostics,D-invalid-suggestion,D-incorrect

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

Hello everyone !

Before I start, this bug report concerns the suggestions the compiler gives when code fails to compile and what happens when we blindly follow them, which is something someone new to the language or new to programming in general might be led to do.

I tried this code:

```rust
fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
where
    T: Copy,
    F: Fn(T) -> T {
    let mut i: usize = 0;
    for value in std::iter::successors(
        Some(a0),
        |x| Some(f(x))
    ).take(N) {
        a[i] = value;
        i += 1;
    }
}

fn main() {
    const N: usize = 10;
    let a0: f64 = 0.5;

    let mut a = [0_f64; N];
    iterator_array_fill(&mut a, &a0, |x| x * (1.0 - x));

    println!("{:?}", a);
}
```

This one doesn't compile and the right way to make it work is the following:

```rust
fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
where
    T: Copy,
    F: Fn(T) -> T {
    let mut i: usize = 0;
    for value in std::iter::successors(
        Some(*a0), // <-- HERE!
        |x| Some(f(*x)) // <-- AND HERE!
    ).take(N) {
        a[i] = value;
        i += 1;
    }
}

fn main() {
    const N: usize = 10;
    let a0: f64 = 0.5;

    let mut a = [0_f64; N];
    iterator_array_fill(&mut a, &a0, |x| x * (1.0 - x));

    println!("{:?}", a);
}
```

The following is the error message output for the first code example:
```
> cargo run
   Compiling bug_fill_array_with_iter v0.1.0
error[E0308]: mismatched types
 --> src\main.rs:8:20
  |
1 | fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
  |                           - this type parameter
...
8 |         |x| Some(f(x)) // works: |x| Some(f(*x))
  |                    ^ expected type parameter `T`, found `&&T`
  |
  = note: expected type parameter `T`
                  found reference `&&T`
help: consider dereferencing the borrow
  |
8 |         |x| Some(f(**x)) // works: |x| Some(f(*x))
  |                    ++

error[E0308]: mismatched types
 --> src\main.rs:8:18
  |
1 | fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
  |                           - this type parameter
...
8 |         |x| Some(f(x)) // works: |x| Some(f(*x))
  |                  ^^^^
  |                  |
  |                  expected `&T`, found type parameter `T`
  |                  help: consider borrowing here: `&f(x)`
  |
  = note:   expected reference `&T`
          found type parameter `T`

error[E0308]: mismatched types
  --> src\main.rs:10:16
   |
1  | fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
   |                           - this type parameter
...
10 |         a[i] = value;
   |         ----   ^^^^^ expected type parameter `T`, found `&T`
   |         |
   |         expected due to the type of this binding
   |
   = note: expected type parameter `T`
                   found reference `&T`
help: consider dereferencing the borrow
   |
10 |         a[i] = *value;
   |                +

For more information about this error, try `rustc --explain E0308`.
error: could not compile `bug_fill_array_with_iter` due to 3 previous errors
```

Implementing these suggestions leads to the following code:

```rust
fn iterator_array_fill<F, T, const N: usize>(a: &mut [T; N], a0: &T, f: F)
where
    T: Copy,
    F: Fn(T) -> T {
    let mut i: usize = 0;
    for value in std::iter::successors(
        Some(a0), // no changes even suggested
        |x| Some(&f(**x)) // bad suggestions
    ).take(N) {
        a[i] = *value; // bad suggestion
        i += 1;
    }
}

fn main() {
    const N: usize = 10;
    let a0: f64 = 0.5;

    let mut a = [0_f64; N];
    iterator_array_fill(&mut a, &a0, |x| x * (1.0 - x));

    println!("{:?}", a);
}
```

Which gives the following compilation error:
```
> cargo run
   Compiling bug_fill_array_with_iter v0.1.0
error[E0515]: cannot return value referencing temporary value
 --> src\main.rs:8:13
  |
8 |         |x| Some(&f(**x)) // works: |x| Some(f(*x))
  |             ^^^^^^------^
  |             |     |
  |             |     temporary value created here
  |             returns a value referencing data owned by the current function

For more information about this error, try `rustc --explain E0515`.
error: could not compile `bug_fill_array_with_iter` due to previous error
```

For which rustc doesn't even bother giving any suggestions. This is a very frustrating behavior for beginners and could potentially lead to people giving up on the language.


`rustc --version --verbose`:
```
<version>
rustc 1.61.0 (fe5b13d68 2022-05-18)
binary: rustc
commit-hash: fe5b13d681f25ee6474be29d748c65adcd91f69e
commit-date: 2022-05-18
host: x86_64-pc-windows-msvc
release: 1.61.0
LLVM version: 14.0.0
```


<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"Ezrashaw"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->