Этот код компилируется:
#[derive(Debug, Default)]
struct Example;
impl Example {
fn some_method(&self) {}
}
fn reproduction() -> Example {
let example = Default::default();
// example.some_method();
example
}
Если закомментированная строка добавлена обратно, это вызовет ошибку:
error[E0282]: type annotations needed
--> src/lib.rs:10:5
|
9 | let example = Default::default();
| ------- consider giving 'example' a type
10 | example.some_method();
| ^^^^^^^ cannot infer type
|
= note: type must be known at this point
Почему добавление этого вызова метода приводит к сбою вывода типа?
Я видел эти два вопроса:
- Как вывод типа Rust работает через несколько операторов?
- Как Rust выводит результирующие типы из From :: <> :: from()?
Из них я знаю, что Rust использует (модифицированную) версию Hindley-Milner. Последний вопрос имеет ответ, который описывает вывод типа Rust как систему уравнений. Другой ответ прямо заявляет, что "Тип информации в Rust может течь в обратном направлении".
Используя эти знания в данной ситуации, мы имеем:
-
example
типа?E
-
?E
должен иметь метод с именемsome_method
-
?E
возвращается - Тип возвращаемого значения -
Example
Работая задом наперед, человеку легко увидеть, что ?E
должно быть Example
. Где разрыв между тем, что я вижу, и тем, что видит компилятор?