Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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