Почему индексация вектора с явно заданным типом завершается ошибкой с выводом типа? - PullRequest
4 голосов
/ 15 июня 2019

В коде ниже я генерирую вектор и затем использую его в качестве содержимого для замыкания:

fn main() {
    let f = {
        let xs: Vec<(usize, usize)> = Vec::new();
        // populate xs
        move |i, j| xs[j].1 - xs[i].0
    };
    let x = f(1usize, 2usize);
}

Почему этот код не компилируется с ошибкой вывода типа, хотявектор явно напечатан?

error[E0282]: type annotations needed
 --> src/main.rs:5:21
  |
5 |         move |i, j| xs[j].1 - xs[i].0
  |                     ^^^^^ cannot infer type
  |
  = note: type must be known at this point

1 Ответ

5 голосов
/ 15 июня 2019

Синтаксис [i] в Rust происходит от реализации черты std::ops::Index .

Эта черта выглядит так:

pub trait Index<Idx> 
where
    Idx: ?Sized, 
{
    type Output: ?Sized;
    fn index(&self, index: Idx) -> &Self::Output;
}

Вы можете реализовать Index для типа несколько раз, каждый из которых имеет свой тип для параметра Idx. Vec поддерживает как можно больше различных механизмов индексации, используя общую реализацию Index:

impl<T, I> Index<I> for Vec<T>
where
    I: SliceIndex<[T]>, 

Это будет работать для любого типа, который также имеет реализацию SliceIndex, которая включает в себя usize, как вы пытались использовать, но также и типы диапазонов, такие как Range<usize> (например, 0..5) и RangeFrom<usize> (например, 0..). Внутри замыкания компилятор не знает , какую реализацию Index планируется использовать, и каждая возможность может иметь свой тип Output, поэтому он не может вывести ни одного введите там.

Вы можете исправить это, комментируя аргументы закрытия:

let f = {
    let xs: Vec<(usize, usize)> = Vec::new();
    //
    move |i: usize, j: usize| xs[j].1 - xs[i].0
};
let x = f(1, 2);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...