rust - 为什么类型推断在存在类型参数默认值的情况下对 `HashMap` 和我自己的结构表现不同?

标签 rust

我有一个带有两个类型参数的结构,其中一个具有默认类型:

use std::marker::PhantomData;

struct Foo<T, F = ()>(PhantomData<(T, F)>);

impl<T, F> Foo<T, F> {
    fn new() -> Self { Self(PhantomData) }
    fn foo(&self, _: T) {}
}


let foo = Foo::new();
foo.foo(0u32);

上面的代码导致:

error[E0282]: type annotations needed
  --> src/main.rs:17:15
   |
17 |     let foo = Foo::new();
   |         ---   ^^^^^^^^ cannot infer type for `F`
   |         |
   |         consider giving `foo` a type

我不明白为什么这里没有使用默认类型。注意说 let foo: Foo<u32> = Foo::new();已经有效——因此无需指定参数 F .但是为什么指定T ?所以我已经很困惑了。

但后来我想起所有这些都适用于 HashMap !它被定义为 struct HashMap<K, V, S = RandomState> .而且我从来不需要指定任何东西。例如,这有效:

use std::collections::HashMap;

let mut map = HashMap::new();
map.insert(0u32, 'x');

( Everything on Playground )

为什么 Foo 之间的默认类型/推理行为不同?和 HashMap ? HashMap 是否使用了一些编译器魔法?

最佳答案

HashMap::new 是这样定义的:

impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
    pub fn new() -> HashMap<K, V, RandomState> {
        Default::default()
    }
}

RandomState是为S提供的new。对于相同的行为,您的代码将如下所示:

impl<T> Foo<T, ()> {
    fn new() -> Self { Self(PhantomData) }
    fn foo(&self, _: T) {}
}

Playground

注意:Default 可用于自定义 BuildHasher:

impl<K, V, S> Default for HashMap<K, V, S>

关于rust - 为什么类型推断在存在类型参数默认值的情况下对 `HashMap` 和我自己的结构表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55616115/

相关文章:

rust - 使用装箱特征对象时,Rust 的生命周期规则是什么?

rust - 不同文件中的结构如何相互引用?

rust - : `instance.method::<SomeThing>()` ? 的语法是什么

error-handling - 在将filter_map与易错的映射功能一起使用时,如何汇总错误的迭代器?

file - 如何仅获取当前可执行文件路径的目录部分?

Rust 实现迭代器

macros - 如何在隐式导出宏时使用模块中定义的构造

for-loop - 元组在for循环中被破坏了吗?

generics - 如何绑定(bind)结构体的泛型类型,使其成为关联函数的具体类型?

rust - Rust 中的 PhantomData 类型用法