为什么编译器需要一个 trait 的实现来调用默认的自由函数?

mal*_*tor 1 types traits rust

当调用一个不带 trait 的默认实现时self,为什么需要注释一个实现类型?

下面是一个最小的、可重复的示例playground):

mod builder {
    pub trait Builder: Sized {
        fn new() -> Simple {
            Simple
        }
    }

    pub struct Simple;

    impl Builder for Simple {}
}

pub fn main() {
    let _ = builder::Builder::new();
    
    /* Working version */
    // use builder::Builder;
    // let _ = builder::Simple::new();
}
Run Code Online (Sandbox Code Playgroud)

这使:

error[E0283]: type annotations needed
  --> src/main.rs:14:13
   |
3  |         fn new() -> Simple {
   |         ------------------ required by `builder::Builder::new`
...
14 |     let _ = builder::Builder::new();
   |             ^^^^^^^^^^^^^^^^^^^^^ cannot infer type
   |
   = note: cannot satisfy `_: builder::Builder`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0283`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.
Run Code Online (Sandbox Code Playgroud)

的编译器解释E0283没有提到默认实现,我同意这是有道理的。但是对于默认实现,为什么需要类型?

pro*_*-fh 5

这不仅是一个默认实现,而且是一个非常特殊的情况,其中这个默认实现在其参数、结果和正文中甚至没有提到Self/ self

我发现更容易理解的规则是,在任何情况下,每次我们使用 trait 时都需要一个类型,而不是« 除非默认实现在其参数、结果和正文中甚至没有提到Self/self

对于这个非常具体的用例,您不想在调用所需函数时显式命名类型,我建议使用免费函数。

mod builder {
    // ...
    pub fn make_default() -> Simple {
        Simple
    }
    // ...
}

pub fn main() {
    let _ = builder::make_default();
}
Run Code Online (Sandbox Code Playgroud)