为什么具有默认值的泛型需要类型注释,而 Vec 在 nightly 中自动推断其分配器?

Mar*_*zer 1 rust

我试图定义一个带有默认类型参数的结构,就像 Vec 每晚在 Rust 中使用它的分配器工作一样。但是,正如其他答案和 Rust 论坛中所解释的,这不是类型推断的工作方式:

use std::marker::PhantomData;

struct Foo<X: Copy = i32> {
    x: PhantomData<X>
}

impl<X: Copy> Foo<X> {
    fn new() -> Foo<X> {
        Foo {
            x: PhantomData
        }
    }
}

fn main() {
    // type annotations needed
    let foo = Foo::new();
    
    // works??
    let mut bar = Vec::new();
    bar.push(42); // to let Rust infer T.
}
Run Code Online (Sandbox Code Playgroud)

我的问题不是为什么Foo::new()不编译,而是为什么Vec::new()仍然编译。如果我删除Foo::new(),文件将编译。据我了解,支持分配器的 Vec 的新定义应该已经破坏了几乎所有代码。

理想情况下,一个答案会向我指出 rustc 中的代码,如果它是一个豁免。

tre*_*tcl 5

定义impl infn new是泛型 over T,但不是A

impl<T> Vec<T> {
    pub const fn new() -> Self {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

由于A具有默认值Global,因此它实现了一个new函数Vec<T, Global>。它没有new为任何其他分配器实现功能。所以Vec::new总是会创建一个新的Vec<_, Global>.

A具有默认值的事实实际上是相切的;解决时没有考虑到这一点Vec::new

你可以用Foo同样的方式工作:

impl Foo<i32> {
    fn new() -> Self {
        Foo { x: PhantomData }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,new总是会创建一个Foo<i32>,如果你想创建一个不同类型的功能Foo,你需要创建一个不同名称的功能,就像Vecnew_in用于指定不同的分配比Global