我正在学习Rust并遇到类似于此的内容
struct A<T> {
some_vec: Vec<T>,
pub secret: &'static str
}
struct B{}
struct C{}
impl B {
fn foo<T>(&self) {
let bar: A<T> = A {
some_vec: Vec::new(),
secret: "123"
};
println!("The secret is {}", bar.secret);
}
}
impl C {
fn foo<T>(&self) {
let b = B{};
b.foo();
}
}
fn main() {
let c = C{};
c.foo();
}
这会产生编译器错误
error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [--explain E0282]
--> src/main.rs:26:11
|>
26 |> b.foo();
|> ^^^
我看过有关同一错误消息的帖子,但在这种情况下我无法找出解决方案。我缺少哪些信息(与b.foo()
相关)?
答案 0 :(得分:8)
由于类型推断对于许多来到Rust的人来说是一个新奇事物,让我们更深入地解释它。
从本质上讲,类型推断有点像那些&#34;迷宫&#34;你可能在杂志上玩过的游戏:
左手边有一堆未知类型的地方,右手连接少数已知类型。如何?好吧,通过检查类型之间的关系!
最简单的关系(无需猜测)是一度的关系:
let x: String = "Hello, World".into();
在Rust中,我们知道into()
来自Into<T>
实施的&str
特征,但是T
?好吧,into()
返回T
,表达式的类型应为String
,因此必须为Into<String>
。
为了解决类型推断,编译器因此会在需要推断类型的位置和已知类型之间构建某种关系图(在Rust中,函数签名必须是显式的,所以它不应该有搜索得太远了,然后会尝试逐渐推断出类型。
让我们检查当前的用例:
fn main() {
let c = C{};
c.foo();
}
此处,c.foo();
调用C::foo<T>()
:我们需要推断T
。我们有什么信息?没有。小人物。纳达。
在这种情况下,无法解决问题,编译器退出并询问您(开发人员)您想要的T
。您可以通过多种方式指定它:
::<>
c.foo::<i32>()
let x: i32 = ...;
_
字符来忽略部分内容,如let x: Vec<_> = ...;
或c.foo::<Vec<_>>()
如果编译器有足够的信息来自行推断_
。答案 1 :(得分:3)
通常,泛型函数将在其参数类型中使用其类型参数。在这种情况下,编译器可以根据调用中的参数类型推断类型参数。
但是,在您的情况下,B::foo
和C::foo
没有使用T
的任何参数。因此,每次调用都需要明确指定T
的具体类型。这是通过在括号之前的函数名称之后添加::<X>
(其中X
是一个类型)来完成的。
在C::foo
中,您可能希望将C::foo
的{{1}}转发给T
,所以您要写:
B::foo
然后在impl C {
fn foo<T>(&self) {
let b = B {};
b.foo::<T>();
}
}
中,您可以使用您想要的任何类型:
main