rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.18k stars 12.7k forks source link

Improve error message for IntoIterator for arrays misuse #86524

Open alexxbb opened 3 years ago

alexxbb commented 3 years ago

With new rustc 1.53.0 IntoIterator for arrays, I naively tried this code and the errors message looks scary and for beginners might be very hard to understand.

Given the following code:

fn main() {
    let vec = vec![10];
    for i in vec.iter().chain([20]){
    }
}

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

The current output is:

   Compiling playground v0.0.1 (/playground)
error[E0271]: type mismatch resolving `<[{integer}; 1] as IntoIterator>::Item == &{integer}`
 --> src/main.rs:3:25
  |
3 |     for i in vec.iter().chain([20]){
  |                         ^^^^^ expected integer, found `&{integer}`

error[E0271]: type mismatch resolving `<std::array::IntoIter<{integer}, 1_usize> as Iterator>::Item == &{integer}`
 --> src/main.rs:3:14
  |
3 |     for i in vec.iter().chain([20]){
  |              ^^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
  |
  = note: required because of the requirements on the impl of `Iterator` for `std::iter::Chain<std::slice::Iter<'_, {integer}>, std::array::IntoIter<{integer}, 1_usize>>`
  = note: required because of the requirements on the impl of `IntoIterator` for `std::iter::Chain<std::slice::Iter<'_, {integer}>, std::array::IntoIter<{integer}, 1_usize>>`
  = note: required by `into_iter`

error[E0271]: type mismatch resolving `<std::array::IntoIter<{integer}, 1_usize> as Iterator>::Item == &{integer}`
 --> src/main.rs:3:14
  |
3 |     for i in vec.iter().chain([20]){
  |              ^^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
  |
  = note: required because of the requirements on the impl of `Iterator` for `std::iter::Chain<std::slice::Iter<'_, {integer}>, std::array::IntoIter<{integer}, 1_usize>>`
  = note: required by `std::iter::Iterator::next`

error: aborting due to 3 previous errors

Ideally the output should look like:

Thanks to @CAD97 for suggested output

error[E0271]: type mismatch resolving `<[{integer}; 1] as IntoIterator>::Item == &{integer}`
 --> src/main.rs:3:25
  |
3 |     for i in vec.iter().chain([20]) {}
  |                         ^^^^^ expected integer, found `&{integer}`
  = help: try iterating by reference instead
        for i in vec.iter().chain(&[20]) {}
                                  ^
  = help: try copying the iterated items
        for i in vec.iter().copied().chain([20]) {}
                           ^^^^^^^^^
  = help: try iterating by value instead
        for i in vec.into_iter().chain([20]) {}
                    ^^^^^^^^^^^^

EDIT: URLO thread https://users.rust-lang.org/t/rust-1-53-intoiterator/61350

leonardo-m commented 3 years ago

It's better to choose only one of those three idioms, and to only suggest that. (Personally I am slightly in preference for the third, with into_iter).