我正在学习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();
}
Run Code Online (Sandbox Code Playgroud)
这会产生编译器错误
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();
|> ^^^
Run Code Online (Sandbox Code Playgroud)
我看过有关同一错误消息的帖子,但在这种情况下我无法找出解决方案.b.foo()我缺少哪些信息(相关)?
由于类型推断对于许多来到Rust的人来说是一个新奇事物,让我们更深入地解释一下.
从本质上讲,类型推断有点像你可能在杂志上玩过的那些"迷宫"游戏:
你有一堆左边未知类型的地方,右边是少数已知类型.如何?那么,通过检查类型之间的关系!
最简单的关系(无需猜测)是一个1度的关系:
let x: String = "Hello, World".into();
Run Code Online (Sandbox Code Playgroud)
在Rust中,我们知道它into()来自Into<T>实现的特性&str,但是哪个T?好吧,into()返回a T并且表达式的类型应该是a String,因此它必须是Into<String>.
因此,为了解决类型推断,编译器将在需要推断类型的位置和已知类型之间构建某种关系图(在Rust中,函数签名必须是显式的,因此它不应该也需要搜索远),然后将尝试一点一点地推断出类型.
我们来看看当前的用例:
fn main() {
let c = C{};
c.foo();
}
Run Code Online (Sandbox Code Playgroud)
在这里,c.foo();电话C::foo<T>():我们需要推断T.我们有什么信息?没有.小人物.纳达.
在这种情况下,无法解决问题,编译器挽救并询问您(开发人员)您想要T的是什么.您可以通过多种方式指定它:
::<>,如c.foo::<i32>()let x: i32 = ...;_字符来消除它的一部分,let x: Vec<_> = ...;或者c.foo::<Vec<_>>()如果编译器有足够的信息来自行推断_.