Repository: rust
Issue: Confusing errors from type (mis-)inference
Labels: A-diagnostics,T-compiler

<!--
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.

If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
the problematic output to occur.
-->

Given the following code: ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=72ec0bfb4ebb032851fc08d57654e699))

```rust
fn main() {
    let mut b = vec![];
    let s = "XYZ".to_string();
    let a: Vec<_> = b.iter().map(|s| f(s)).collect();
    b.push(s);
}

fn f(s: &str) -> String {
    s.to_string()
}
```

The current output is:

```
Compiling playground v0.0.1 (/playground)
error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:4:30
  |
4 |     let a: Vec<_> = b.iter().map(|s| f(s)).collect();
  |                              ^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
  = help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>`
  = note: required because of the requirements on the impl of `Iterator` for `std::slice::Iter<'_, str>`

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:4:21
  |
4 |     let a: Vec<_> = b.iter().map(|s| f(s)).collect();
  |                     ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `std::slice::Iter`

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:4:23
  |
4 |     let a: Vec<_> = b.iter().map(|s| f(s)).collect();
  |                       ^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `core::slice::<impl [T]>::iter`

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:2:17
  |
2 |     let mut b = vec![];
  |                 ^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec::<T>::new`
  = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the size for values of type `str` cannot be known at compilation time
 --> src/lib.rs:2:17
  |
2 |     let mut b = vec![];
  |                 ^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Vec`
  = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): the method `collect` exists for struct `Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>`, but its trait bounds were not satisfied
 --> src/lib.rs:4:44
  |
4 |     let a: Vec<_> = b.iter().map(|s| f(s)).collect();
  |                                            ^^^^^^^ method cannot be called on `Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>` due to unsatisfied trait bounds
  |
  = note: the following trait bounds were not satisfied:
          `str: Sized`
          which is required by `Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>: Iterator`
          `std::slice::Iter<'_, str>: Iterator`
          which is required by `Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>: Iterator`
          `Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>: Iterator`
          which is required by `&mut Map<std::slice::Iter<'_, str>, [closure@src/lib.rs:4:34: 4:37]>: Iterator`

error[[E0599]](https://doc.rust-lang.org/stable/error-index.html#E0599): the method `push` exists for struct `Vec<str>`, but its trait bounds were not satisfied
 --> src/lib.rs:5:7
  |
5 |     b.push(s);
  |       ^^^^ method cannot be called on `Vec<str>` due to unsatisfied trait bounds
  |
  = note: the following trait bounds were not satisfied:
          `str: Sized`

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground` due to 7 previous errors
```

but all of these errors can be summarized to a single root cause: `b` is being inferred to `Vec<str>` due to a call to `to_string`.

If I move `b.push(s)` line to before the offending line:

```rs
fn main() {
    let mut b = vec![];
    let s = "XYZ".to_string();
    b.push(s);
    let a: Vec<_> = b.iter().map(|s| f(s)).collect();
}

fn f(s: &str) -> String {
    s.to_string()
}
```

or relax the parameter type of `f` like this:

```rs
fn main() {
    let mut b = vec![];
    let s = "XYZ".to_string();
    let a: Vec<_> = b.iter().map(|s| f(s)).collect();
    b.push(s);
}

fn f(s: &impl std::ops::Deref<Target=str>) -> String {
    s.to_string()
}
```

then `b` is correctly inferred to `Vec<String>` and all the errors are magically gone.

It looks kinda obvious to me that `b`'s types inferred at `f(s)` and `b.push(s)` conflict with each other, and the conflict can then be automatically resolved with Deref coercion. Even an error pointing directly to `b`'s type would be immensely more helpful than the current wall of errors.

<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->

<!--
If dramatically different output is caused by small changes, consider also
adding them here.

If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->