【发布时间】:2019-04-10 15:18:03
【问题描述】:
我有一个带有两个类型参数的结构,其中一个具有默认类型:
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');
为什么Foo 和HashMap 之间的默认类型/推理行为不同?哈希图是否使用了一些编译器魔法?
【问题讨论】:
-
即使
let foo: Foo<_> = Foo::new();也可以正常工作,因为可以推断出T。看起来它没有提供任何额外的信息,但实际上它确实提供了——显式省略类型构造函数的第二个参数告诉编译器使用默认值。没有任何类型注释的代码的行为类似于let foo: Foo<_, _> = Foo::new();,它失败并出现相同的错误。
标签: rust