此代码编译:

#[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

为什么添加此方法调用会导致类型推断失败?

我看到了这两个问题:

米尔纳的印地语版本是modified.后一个问题有an answer个,将Rust的类型推断描述为一个方程组.Another answer明确指出"Rust中的类型信息可以向后流动".

将这些知识应用于这种情况,我们已经:

  1. example?E
  2. ?E必须有一个名为some_method的方法
  3. ?E美元被退回
  4. 返回类型为Example

向后看,人类很容易看出?E一定是Example.我能看到的和编译器能看到的之间的差距在哪里?

推荐答案

根据已知事实(见下文),它无法编译,因为:

  • 类型判断器通过函数in the order it was written
  • let example = Default::default();中,example可以是实现Default的任何东西,
  • 实地访问及;方法调用需要已知类型,
  • "任何实现Default的东西"都不是已知类型.

我用字段访问替换了some_method(),它会产生同样的错误.


Type inference depends on ordering (#42333)开始:

use std::path::PathBuf;

pub struct Thing {
    pub f1: PathBuf,
}

fn junk() -> Vec<Thing> {
    let mut things = Vec::new();
    for x in vec![1, 2, 3] {
        if x == 2 {
            for thing in things.drain(..) {
                thing.f1.clone();
            }
            return vec![]
        }
        things.push(Thing{f1: PathBuf::from(format!("/{}", x))});
    }   
    things  
}               

fn main() { 
    junk();
}

这会产生Rust 1.33.0的编译器错误:

error[E0282]: type annotations needed
  --> src/main.rs:13:17
   |
9  |     let mut things = Vec::new();
   |         ---------- consider giving `things` a type
...
13 |                 thing.f1.clone();
   |                 ^^^^^ cannot infer type
   |
   = note: type must be known at this point

您应该关注eddyb(Rust语言设计团队since May, 2016的知名成员)的以下 comments .

Comment #1:

这是顺序类型判断器的已知限制.当inference自由流动时,thing.f1.clone()被选中before things.push(Thing {...}),所以当你试图访问f1字段时,thing: Thing是未知的.我们将来可能会远离这一点,但目前还没有立即的计划.

更重要的是comment #2:

我的意思是,类型判断器通过函数in the order it was written.[...] 字段访问和方法调用不受支持,除非类型为is already known.

Rust相关问答推荐

无法在线程之间安全地发送future (&Q;)&错误

关于Rust 中回归的逻辑

我如何在Rust中使用传递依赖中的特征?

如何在Rust中表示仅具有特定大小的数组

无法理解铁 rust &S错误处理

将数组转换为HashMap的更简单方法

为什么我们需要std::thread::scope,如果我们可以使用thread.join()在函数的生命周期内删除引用?

获取与父字符串相关的&;str的原始片段

无法实现整型类型的泛型FN

rust中的库插件管理器,现在是否可行?

实现 Deref 的 struct 可以返回对外部数据的引用吗?

在1.5n次比较中找到整数向量中的最大和次大整数

(let b = MyBox(5 as *const u8); &b; ) 和 (let b = &MyBox(5 as *const u8); ) 之间有什么区别

将 `&T` 转换为新类型 `&N`

SDL2 没有在终端键上触发?

如何在 Rust Polars 中可靠地连接 LazyFrames

为什么指定生命周期让我返回一个引用?

将一片字节复制到一个大小不匹配的数组中

Rust,我如何正确释放堆分配的内存?

为实现特征的所有类型实现显示