Skip to content

On -> impl Iterator<Item = Ty> point at method chains in returned expression where Item might have diverged #106993

Open
@estebank

Description

@estebank

Code

fn foo(items: &mut Vec<u8>){
    items.sort();
}

fn bar() -> impl Iterator<Item = i32> {
    let mut x: Vec<Vec<u8>> = vec![
        vec![0, 2, 1],
        vec![5, 4, 3],
    ];
    x.iter_mut().map(foo)
}

fn main() {
    bar();
}

Current output

error[E0271]: expected `for<'a> fn(&'a mut Vec<u8>) {foo}` to be a fn item that returns `i32`, but it returns `()`
 --> src/main.rs:5:13
  |
5 | fn bar() -> impl Iterator<Item = i32> {
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `i32`
  |
  = note: required for `Map<std::slice::IterMut<'_, Vec<u8>>, for<'a> fn(&'a mut Vec<u8>) {foo}>` to implement `Iterator`

Desired output

error[E0271]: expected `for<'a> fn(&'a mut Vec<u8>) {foo}` to be a fn item that returns `i32`, but it returns `()`
  --> src/main.rs:5:13
   |
LL | fn bar() -> impl Iterator<Item = i32> {
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `i32`
   |
   = note: required for `Map<std::slice::IterMut<'_, Vec<u8>>, for<'a> fn(&'a mut Vec<u8>) {foo}>` to implement `Iterator`
note: the method call chain might not have had the expected associated types
  --> src/main.rs:10:18
   |
LL |       let mut x: Vec<Vec<u8>> = vec![
   |  _______________________________-
LL | |         vec![0, 2, 1],
LL | |         vec![5, 4, 3],
LL | |     ];
   | |_____- this expression has type `Vec<Vec<u8>>`
LL |       x.iter_mut().map(foo)
   |         ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here
   |         |
   |         `Iterator::Item` is `&mut Vec<u8>` here

Rationale and extra context

Similar to what we do on method calls, introduced in #105332 and #105674:

error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `()`
  --> src/main.rs:10:27
   |
10 |     x.iter_mut().map(foo).collect::<Vec<i32>>();
   |                           ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
   |
   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
   = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: the method call chain might not have had the expected associated types
  --> src/main.rs:10:18
   |
6  |       let mut x: Vec<Vec<u8>> = vec![
   |  _______________________________-
7  | |         vec![0, 2, 1],
8  | |         vec![5, 4, 3],
9  | |     ];
   | |_____- this expression has type `Vec<Vec<u8>>`
10 |       x.iter_mut().map(foo).collect::<Vec<i32>>();
   |         ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here
   |         |
   |         `Iterator::Item` is `&mut Vec<u8>` here
note: required by a bound in `collect`
  --> /rustc/4781233a77e879e49cb5ce3c98d2abba6a6ade7a/library/core/src/iter/traits/iterator.rs:1856:5

Other cases

No response

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsE-hardCall for participation: Hard difficulty. Experience needed to fix: A lot.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions