Type inference of a captured variable in a closure

Hi,

When I compile the following snippet

fn main() {
    let a: Vec<Vec<usize>> = (0..10).map(|i| vec![i; i]).collect();
    let f = |j| { a[j].is_empty() };
    println!("{}", f(0));
}

I get

   Compiling type-annot v0.1.0 (/tmp/type-annot)
error[E0282]: type annotations needed
 --> src/main.rs:3:20
  |
3 |     let f = |j| { &a[j].is_empty() };
  |                    ^^^^ cannot infer type
  |
  = note: type must be known at this point

I do not understand why as the type if a is explicitly stated. I can help the compiler using

fn main() {
    let a: Vec<Vec<usize>> = (0..10).map(|i| vec![i; i]).collect();
    let f = |j| { let aj: &Vec<_> = &a[j];
                  aj.is_empty() };
    println!("{}", f(0));
}

but why is it needed?

It's confused about whether j is an usize or a Range<usize>. In the first case, the expression returns a &Vec<_> and in the other case, it returns a &[Vec<_>], so giving a type hint helps it figure out which one.

By the way, the & in &a[j].is_empty() binds like this: &(a[j].is_empty()), and it does not bind to the a[j]. The result of this is a reference to a boolean.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.